J'ai une table InnoDB assez occupée (200 000 lignes, je suppose quelque chose comme des dizaines de requêtes par seconde). En raison d'un bug, j'ai reçu 14 lignes contenant (les mêmes) adresses e-mail invalides et je voulais les supprimer.
J'ai simplement essayé DELETE FROM table WHERE email='invalid address'
et obtenu "Délai d'attente de verrouillage dépassé" après environ 50 secondes. Ce n'est pas très surprenant, car la colonne de ligne n'est pas indexée.
Cependant, je l'ai ensuite fait SELECT id FROM table WHERE email='invalid address'
et cela a pris 1,25 seconde. L'exécution DELETE FROM table WHERE id in (...)
, copier-coller les identifiants du résultat SELECT, a pris 0,02 seconde.
Que se passe-t-il? Quelqu'un peut-il expliquer pourquoi la SUPPRESSION avec la condition est si lente qu'elle expire, mais faire SELECT puis supprimer par id est si rapide?
Merci.
EDIT: Sur demande, j'ai publié la structure du tableau ainsi que certains explain
résultats. Je dois également noter qu'aucune clé étrangère ne fait référence à ce tableau.
Cependant, la situation me semble simple: j'ai un champ non indexé que je sélectionne. Cela nécessite de scanner toute la table, mais ce n'est pas terriblement grand. id
est la clé primaire, donc la suppression par id est très rapide, comme il se doit.
mysql> show create table ThreadNotification2 \G
*************************** 1. row ***************************
Table: ThreadNotification2
Create Table: CREATE TABLE `ThreadNotification2` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`alertId` bigint(20) DEFAULT NULL,
`day` int(11) NOT NULL,
`frequency` int(11) DEFAULT NULL,
`hour` int(11) NOT NULL,
`email` varchar(255) DEFAULT NULL,
`highlightedTitle` longtext,
`newReplies` bit(1) NOT NULL,
`numReplies` int(11) NOT NULL,
`postUrl` longtext,
`sendTime` datetime DEFAULT NULL,
`sent` bit(1) NOT NULL,
`snippet` longtext,
`label_id` bigint(20) DEFAULT NULL,
`organization_id` bigint(20) DEFAULT NULL,
`threadEntity_hash` varchar(255) DEFAULT NULL,
`user_uid` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK3991E9D279251FE` (`organization_id`),
KEY `FK3991E9D35FC0C96` (`label_id`),
KEY `FK3991E9D3FFC22CB` (`user_uid`),
KEY `FK3991E9D5376B351` (`threadEntity_hash`),
KEY `scheduleSentReplies` (`day`,`frequency`,`hour`,`sent`,`numReplies`),
KEY `sendTime` (`sendTime`),
CONSTRAINT `FK3991E9D279251FE` FOREIGN KEY (`organization_id`) REFERENCES `Organization` (`id`),
CONSTRAINT `FK3991E9D35FC0C96` FOREIGN KEY (`label_id`) REFERENCES `Label` (`id`),
CONSTRAINT `FK3991E9D3FFC22CB` FOREIGN KEY (`user_uid`) REFERENCES `User` (`uid`),
CONSTRAINT `FK3991E9D5376B351` FOREIGN KEY (`threadEntity_hash`) REFERENCES `ThreadEntity` (`hash`)
) ENGINE=InnoDB AUTO_INCREMENT=4461945 DEFAULT CHARSET=utf8
1 row in set (0.08 sec)
mysql> explain SELECT * FROM ThreadNotification2 WHERE email='invalid address';
+----+-------------+---------------------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | ThreadNotification2 | ALL | NULL | NULL | NULL | NULL | 197414 | Using where |
+----+-------------+---------------------+------+---------------+------+---------+------+--------+-------------+
1 row in set (0.03 sec)
mysql> explain select * from ThreadNotification2 where id in (3940042,3940237,3941132,3941255,3941362,3942535,3943064,3944134,3944228,3948122,3953081,3957876,3963849,3966951);
+----+-------------+---------------------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | ThreadNotification2 | range | PRIMARY | PRIMARY | 8 | NULL | 14 | Using where |
+----+-------------+---------------------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> delete from ThreadNotification2 where email='invalid address';
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> select id from ThreadNotification2 where email='invalid address';
+---------+
| id |
+---------+
| 3940042 |
| 3940237 |
| 3941132 |
| 3941255 |
| 3941362 |
| 3942535 |
| 3943064 |
| 3944134 |
| 3944228 |
| 3948122 |
| 3953081 |
| 3957876 |
| 3963849 |
| 3966951 |
+---------+
14 rows in set (1.25 sec)
mysql> delete from ThreadNotification2 where id in (3940042,3940237,3941132,3941255,3941362,3942535,3943064,3944134,3944228,3948122,3953081,3957876,3963849,3966951);
Query OK, 14 rows affected (0.02 sec)
la source
SHOW CREATE TABLE
et probablementEXPLAIN...
aussi.email
n'est pas indexé, alors les deuxDELETE
etSELECT
devraient fonctionner également lentement. Ou: Vous dites que la table est fortement interrogée. Peut-être que lorsque vous avez essayé votre premier,DELETE
il y avait quelqu'un d'autre qui effectuait une très longue transaction sur ces lignes ...DELETE FROM ThreadNotification2 WHERE email='invalid address';
peut-être aiderait aussi ...EXPLAIN DELETE FROM....
, cela ne fonctionnera pas. D'après ce que je sais, cela ne fonctionne que sur l'SELECT
al.Réponses:
Si le champ
email
n'est pas indexé, alors les deuxDELETE
etSELECT
devraient fonctionner également lentement.La seule possibilité à laquelle je peux penser est: vous dites que la table est très utilisée. Peut-être que quelqu'un d'autre a exécuté une très longue transaction (impliquant directement ou indirectement ces lignes spécifiques) pendant que vous tentiez d'exécuter le
DELETE
.Je pense que vous devriez peut-être y insérer quelques fausses lignes et essayer de les supprimer. Faites cela 2 ou 3 fois. S'il y a une grande différence dans la durée du
DELETE
, alors la charge DB est probablement la raison.PS: Ne faites cela que si les gens ne seront pas ennuyés par ces fausses lignes: D.
la source