2010-12-02 55 views
2

tableau:La meilleure façon de supprimer 5K lignes de la table InnoDB avec 30M lignes

  • foreign_id_1
  • foreign_id_2
  • entier
  • date1
  • date2
  • primaire (foreign_id_1, foreign_id_2)

Requête: delete from table where (foreign_id_1 = ? or foreign_id_2 = ?) and date2 < ?

Sans requête de date prend environ 40 secondes. C'est trop élevé :(Avec date beaucoup plus longtemps ..

Les options sont:

  • create une autre table et insertselect, puis rename
  • limite d'utilisation et d'exécuter la requête plusieurs fois
  • requête fractionnée à exécuter pour foreign_id_1 puis foreign_id_2
  • utiliser sélectionner, puis supprimer par une seule ligne

Y at-il un moyen plus rapide?


mysql> explain select * from compatibility where user_id = 193 or person_id = 193 \G 
      id: 1 
    select_type: SIMPLE 
     table: compatibility 
     type: index_merge 
possible_keys: PRIMARY,compatibility_person_id_user_id 
      key: PRIMARY,compatibility_person_id_user_id 
     key_len: 4,4 
      ref: NULL 
     rows: 2 
     Extra: Using union(PRIMARY,compatibility_person_id_user_id); Using where 
1 row in set (0.00 sec) 

mysql> explain select * from compatibility where (user_id = 193 or person_id = 193) and updated_at < '2010-12-02 22:55:33' \G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: compatibility 
     type: index_merge 
possible_keys: PRIMARY,compatibility_person_id_user_id 
      key: PRIMARY,compatibility_person_id_user_id 
     key_len: 4,4 
      ref: NULL 
     rows: 2 
     Extra: Using union(PRIMARY,compatibility_person_id_user_id); Using where 
1 row in set (0.00 sec) 
+0

S'il vous plaît poster les résultats d'un 'EXPLAIN' sur votre requête. Mon argent est sur l'indexation insuffisante. – Blrfl

+0

Ajout d'explications de requête – zhekanax

+0

La combinaison des options 3 et 4 est une bonne façon de procéder, à condition que vos SELECTS soient suffisamment rapides. Vous ne pouvez pas vous tromper avec les suppressions PK. :) – Riedsio

Répondre

0

La quantité de données est maintenant de 40M (+33%) et augmente rapidement. J'ai donc commencé à chercher d'autres solutions, certaines non-SQL.

Merci.

2

Avoir un OR dans votre WHERE fait MySQL réticente (sinon refuser complètement) d'utiliser des index sur vos user_id et/ou person_id champs (en cas de - montrant la CREATE TABLE indiquerait s'il était).

Si vous pouvez ajouter des index (ou de modifier ceux qui existent déjà depuis que je pense des indices composés), je probablement ajouter deux:

ALTER TABLE compatibility 
ADD INDEX user_id_updated_at (user_id, updated_at), 
ADD INDEX persona_id_updated_at (person_id, updated_at); 

Corrélativement, en supposant que les lignes à DELETE n'a pas eu à être supprimé atomiquement (c'est-à-dire se produire au même instant).

DELETE FROM compatibility WHERE user_id = 193 AND updated_at < '2010-12-02 22:55:33'; 

DELETE FROM compatibility WHERE person_id = 193 AND updated_at < '2010-12-02 22:55:33'; 
+1

Même la suppression doit être atomique, cela pourrait être accompli avec une transaction InnoDB. – Sonny

+0

@ Sonny - assez vrai. Re-lire son message, la dernière idée «utiliser sélectionner puis supprimer par une seule ligne», indique qu'il irait bien. – Riedsio