Ich habe eine ziemlich ausgelastete InnoDB-Tabelle (200.000 Zeilen, ich denke so etwas wie Dutzende von Abfragen pro Sekunde). Aufgrund eines Fehlers habe ich 14 Zeilen mit (denselben) ungültigen E-Mail-Adressen erhalten und wollte diese löschen.
Ich habe einfach versucht DELETE FROM table WHERE email='invalid address'
und nach ca. 50 Sekunden "Wartezeitüberschreitung der Sperre überschritten". Dies ist nicht besonders überraschend, da die Zeilenspalte nicht indiziert ist.
Allerdings habe ich das dann gemacht SELECT id FROM table WHERE email='invalid address'
und das hat 1,25 Sekunden gedauert. Das Ausführen DELETE FROM table WHERE id in (...)
, Kopieren und Einfügen der IDs aus dem SELECT-Ergebnis, dauerte 0,02 Sekunden.
Was ist los? Kann jemand erklären, warum das LÖSCHEN mit der Bedingung so langsam ist, dass die Zeit abläuft, aber SELECT auszuführen und dann nach ID zu löschen, ist so schnell?
Vielen Dank.
EDIT: Auf Wunsch habe ich die Tabellenstruktur sowie einige explain
Ergebnisse gepostet . Ich sollte auch beachten, dass es keine Fremdschlüssel gibt, die auf diese Tabelle verweisen.
Die Situation scheint mir jedoch einfach zu sein: Ich habe ein nicht indiziertes Feld, gegen das ich mich wähle. Dies erfordert das Scannen des gesamten Tisches, ist jedoch nicht besonders groß. id
ist der Primärschlüssel, daher ist das Löschen nach ID sehr schnell, wie es sein sollte.
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)
email
indiziert ist, sollten beide DELETE
und SELECT
gleich langsam arbeiten. Oder: Sie sagen, dass die Tabelle stark abgefragt wird. Vielleicht hat bei Ihrem ersten Versuch DELETE
jemand anderes eine wirklich lange Transaktion in diesen Zeilen ausgeführt ...
DELETE FROM ThreadNotification2 WHERE email='invalid address';
vielleicht würde auch helfen ...
EXPLAIN DELETE FROM....
, wird es nicht funktionieren. Soweit ich weiß, funktioniert es nur auf SELECT
s.
SHOW CREATE TABLE
und wahrscheinlich auch einenEXPLAIN...
.