Saya memiliki tabel InnoDB yang cukup sibuk (200.000 baris, saya kira kira-kira puluhan pertanyaan per detik). Karena bug, saya mendapat 14 baris dengan alamat email (yang sama) tidak valid di dalamnya dan ingin menghapusnya.
Saya hanya mencoba DELETE FROM table WHERE email='invalid address'
dan mendapatkan "Batas waktu tunggu tunggu melebihi" setelah sekitar 50 detik. Ini tidak terlalu mengejutkan, karena kolom baris tidak diindeks.
Namun, saya kemudian melakukannya SELECT id FROM table WHERE email='invalid address'
dan itu butuh 1,25 detik. Menjalankan DELETE FROM table WHERE id in (...)
, menyalin-menempelkan id dari hasil SELECT, butuh 0,02 detik.
Apa yang sedang terjadi? Adakah yang bisa menjelaskan mengapa DELETE dengan kondisinya sangat lambat sehingga tidak aktif, tetapi melakukan SELECT dan kemudian menghapus dengan id begitu cepat?
Terima kasih.
EDIT: Atas permintaan, saya memposting struktur tabel serta beberapa explain
hasil. Saya juga harus mencatat bahwa tidak ada kunci asing yang merujuk pada tabel ini.
Namun, situasinya tampak langsung bagi saya: Saya memiliki bidang yang tidak tereksplorasi yang saya pilih. Ini membutuhkan pemindaian seluruh tabel, tetapi itu tidak terlalu besar. id
adalah kunci utama, jadi menghapus dengan id sangat cepat, sebagaimana mestinya.
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)
sumber
SHOW CREATE TABLE
dan mungkinEXPLAIN...
juga.email
tidak terindeks, maka keduanyaDELETE
danSELECT
harus bekerja sama lambat. Atau: Anda mengatakan bahwa tabel itu sangat ditanyakan. Mungkin ketika Anda mencoba pertama AndaDELETE
ada orang lain menjalankan transaksi yang sangat panjang pada baris-baris itu ...DELETE FROM ThreadNotification2 WHERE email='invalid address';
EXPLAIN DELETE FROM....
, itu tidak akan berfungsi. Dari apa yang saya tahu, ini hanya berfungsi padaSELECT
s.Jawaban:
Jika bidang
email
tidak terindeks, maka keduanyaDELETE
danSELECT
harus bekerja sama lambat.Satu-satunya kemungkinan yang dapat saya pikirkan adalah: Anda mengatakan bahwa tabel tersebut sangat diakses. Mungkin orang lain menjalankan transaksi yang sangat panjang (melibatkan langsung atau tidak langsung baris-baris spesifik itu) ketika Anda mencoba untuk mengeksekusi
DELETE
.Saya pikir mungkin Anda harus memasukkan beberapa baris tiruan di sana dan mencoba untuk menghapusnya. Lakukan itu 2 atau 3 kali. Jika ada perbedaan besar dalam durasi
DELETE
, maka beban DB mungkin menjadi alasannya.PS: Lakukan itu hanya jika orang tidak akan terganggu oleh baris tiruan itu: D.
sumber