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)
quelle
SHOW CREATE TABLE
und wahrscheinlich auch einenEXPLAIN...
.email
indiziert ist, sollten beideDELETE
undSELECT
gleich langsam arbeiten. Oder: Sie sagen, dass die Tabelle stark abgefragt wird. Vielleicht hat bei Ihrem ersten VersuchDELETE
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 aufSELECT
s.Antworten:
Wenn das Feld nicht
email
indiziert ist, sollten beideDELETE
undSELECT
gleich langsam arbeiten.Die einzige Möglichkeit, an die ich denken kann, ist: Sie sagen, dass auf die Tabelle stark zugegriffen wird. Möglicherweise hat eine andere Person eine sehr lange Transaktion ausgeführt (die direkt oder indirekt diese bestimmten Zeilen einbezieht), während Sie versuchten, die auszuführen
DELETE
.Ich denke, vielleicht sollten Sie dort einige Scheinzeilen einfügen und versuchen, sie zu löschen. Mach das 2 oder 3 mal. Wenn es einen großen Unterschied in der Dauer der gibt
DELETE
, dann ist die DB-Last wahrscheinlich der Grund.PS: Tun Sie das nur, wenn die Leute sich nicht über diese Scheinreihen ärgern: D.
quelle