2010-05-21 3 views
1

que je fais ceci:supprimer prendre très longtemps! mysql

delete calibration_2009 from 
calibration_2009 join batchinfo_2009 
on calibration_2009.rowid = batchinfo_2009.rowid 
where batchinfo_2009.reporttime like '%2010%'; 

les deux tables ont environ 500k lignes de données je soupçonne que 250k correspondent aux critères à supprimer

jusqu'à présent, il a fonctionné pendant 2 heures !!! y a-t-il quelque chose qui ne va pas?

dev.mysql.com dit que je dois faire ceci:

If you are deleting many rows from a large table, you may exceed the lock table size for an InnoDB table. To avoid this problem, or simply to minimize the time that the table remains locked, the following strategy (which does not use DELETE at all) might be helpful: 

Select the rows not to be deleted into an empty table that has the same structure as the original table: 

INSERT INTO t_copy SELECT * FROM t WHERE ... ; 
Use RENAME TABLE to atomically move the original table out of the way and rename the copy to the original name: 

RENAME TABLE t TO t_old, t_copy TO t; 
Drop the original table: 

DROP TABLE t_old; 

comment je ne le fais avec ma déclaration actuelle?

+0

C'est probablement juste parce que 250 + k est beaucoup de données à supprimer, et prendrait un certain temps –

+0

duplication possible de [moyen le plus rapide de supprimer des données de mysql] (http://stackoverflow.com/questions/2884385/quickest- way-of-deleting-data-from-mysql) –

+1

Généralement, je fais un compte de sélection (*) à partir de ... avant d'exécuter une suppression réelle pour m'assurer que je reçois au moins la bonne quantité de lignes et un select *. .. limite 100 (ou plus) pour s'assurer que les lignes semblent correctes. Si vous exécutez cette opération dans une transaction, vous pouvez envisager d'abandonner et de vérifier que vous supprimez réellement ce que vous attendiez. –

Répondre

2

Certaines choses à penser et essayer:

  • Êtes-vous sûr que Rowid est votre clé primaire?
  • S'agit-il des mêmes types de données?
  • Avez-vous un index construit dessus?
  • Envelopper la suppression dans une transaction
  • Confirmez que vous n'avez aucun déclencheur actif à partir de la suppression.

  • Pouvez-vous publier le schéma de la table?

  • En outre, exécutez la requête par la Query Analyser pour confirmer les jointures se passent correctement

SCRIPT COPIER TABLEAU:

INSERT INTO calibration_2009_copy 
SELECT calibration_2009.* 
FROM calibration_2009 
JOIN batchinfo_2009 
    ON calibration_2009.rowid = batchinfo_2009.rowid 
WHERE batchinfo_2009.reporttime not like '%2010%'; 

RENAME TABLE calibration_2009 TO calibration_2009_old; 
RENAME TABLE calibration_2009_copy TO calibration_2009; 

DROP TABLE calibration_2009_old; 
+0

noah yasher koach vous êtes l'homme ont une grande shabbas –

+1

Content de vous aider. Avez-vous utilisé le script de copie de table, ou trouvez-vous ce qui causait le problème en premier lieu? – Noah

+0

J'ai utilisé le morceau de code que vous aviez suggéré. Je suppose que j'essayais juste de supprimer trop de lignes et ma déclaration de sélection a pris trop de temps je ne sais pas –

1

Essayez d'ajouter un index pour batchinfo_2009.reporttime et rowid voir aussi s'il y a des verrous de table en cas d'utilisation MyISAM

0

Je ne; sais pas à propos de MySQL, mais ce '% 2010%' garantirait une analyse de table dans SQl Server. Cela ralentirait certainement les choses.

+0

Vrai, mais 500k lignes ne sont pas beaucoup à analyser, juste quelques secondes, sauf si sa machine est "REAL SLOW". Sur ma machine, je numérise un peu plus de 80K lignes/seconde – Noah

0
WHERE batchinfo_2009.reporttime NOT LIKE '%2010%'; 

C'est probablement la raison pour laquelle la requête est si lente. L'utilisation de LIKE, en particulier avec un caractère générique au début de la chaîne, empêchera la requête d'utiliser un index sur reporttime.

Une meilleure requête serait:

DELETE calibration_2009 
FROM calibration_2009 
JOIN batchinfo_2009 
ON calibration_2009.rowid = batchinfo_2009.rowid 
WHERE batchinfo_2009.reporttime NOT BETWEEN MAKE_DATE(2010, 1) AND MAKE_DATE(2010, 365); 
#`repporttime` is a TIMESTAMP 

Ceci effectuer une analyse de gamme sur repporttime à l'aide d'un index.

Questions connexes