2010-03-05 8 views
12

J'ai une assez grande table avec 19 000 000 d'enregistrements, et j'ai des problèmes avec les lignes en double. Il y a beaucoup de questions similaires ici même dans SO, mais aucune d'entre elles ne semble me donner une réponse satisfaisante. Quelques points à considérer:Supprimer des doublons d'une grande table

  • unicité de la ligne est déterminée par deux colonnes, location_id et datetime.
  • Je voudrais garder le temps d'exécution aussi vite que possible (< 1 heure).
  • La copie de tableaux n'est pas très pratique car la taille de la table est de plusieurs gigaoctets.
  • Pas besoin de s'inquiéter des relations.

Comme dit, chaque location_id peut avoir qu'une seule datetime distincte, et je voudrais supprimer toutes les instances en double. Peu importe lequel survit, car les données sont identiques.

Des idées?

+3

Envisagez de supprimer temporairement les index, les triggers s'il existe. – Pentium10

+0

Quel était le problème avec l'approche donnée dans http://stackoverflow.com/questions/1585412/sql-to-delete-duplicate-records-in-a-table? – Mike

+0

@ Pentium10, bon point, pourrait accélérer les choses, mais pourrait également tuer les performances si je passe par la solution de sous-requête. –

Répondre

15

Je pense que vous pouvez utiliser cette requête pour supprimer les enregistrements en double de la table

ALTER IGNORE TABLE table_name ADD UNIQUE (location_id, datetime) 

Avant de le faire , juste tester avec quelques exemples de données d'abord .. puis Essayez ceci ....

Note: Sur la version 5.5, cela fonctionne sur MyISAM mais pas sur InnoDB.

+0

Cela semble prometteur, je n'avais pas entendu parler de cette fonctionnalité avant. En essayant maintenant, je vous ferai savoir comment cela se passe. Et bienvenue à SO :) –

+6

Cela a fonctionné, merci. A pris 31 minutes pour passer par 16 982 040 lignes avec 1 589 908 doublons.Je ne peux pas croire que cela pourrait être aussi simple, sans tables supplémentaires ou requêtes complexes. :) –

+0

@Vinodkumar Saravana, je cours 5.5 avec InnoDB, j'ai lu votre note mais je l'ai essayé de toute façon juste pour être sûr. (Bien sûr, cela n'a pas fonctionné), mais pouvez-vous expliquer pourquoi cela ne fonctionne pas sur InnoDB? – tixastronauta

1
SELECT *, COUNT(*) AS Count 
FROM table 
GROUP BY location_id, datetime 
HAVING Count > 2 
0
UPDATE table SET datetime = null 
WHERE location_id IN (
SELECT location_id 
FROM table as tableBis 
WHERE tableBis.location_id = table.location_id 
AND table.datetime > tableBis.datetime) 

SELECT * INTO tableCopyWithNoDuplicate FROM table WHERE datetime is not null 

DROp TABLE table 

RENAME tableCopyWithNoDuplicate to table 

Vous gardez la ligne avec le datetime inférieur. Je ne suis pas sûr de perf, cela dépend de votre colonne de table, votre serveur etc ...

0

Cette requête fonctionne parfaitement pour tous les cas: testé pour Moteur: MyIsam pour 2 millions de lignes.

ALTER IGNORE TABLE nom_table ADD UNIQUE (location_id, datetime)

0

Vous pouvez supprimer les doublons en procédant comme suit: 1- Exporter les résultats de la requête suivante dans un fichier txt:

select dup_col from table1 group by dup_col having count(dup_col) > 1 

2- Ajouter ceci au premier du fichier ci-dessus txt et exécuter la requête finale:

delete from table1 where dup_col in (.....) 

S'il vous plaît noter que « ... » est le contenu du fichier txt créé i n la première étape.

Questions connexes