เหตุใด DELETE จึงช้ากว่า SELECT มากแล้วจึงลบตาม id


12

ฉันมีตาราง InnoDB ที่ค่อนข้างยุ่ง (200,000 แถวฉันเดาได้ว่ามีหลายสิบข้อความค้นหาต่อวินาที) เนื่องจากข้อผิดพลาดฉันได้รับ 14 แถวที่มีที่อยู่อีเมลไม่ถูกต้อง (เหมือนกัน) และต้องการลบทิ้ง

ฉันลองDELETE FROM table WHERE email='invalid address'และได้รับ "เกินเวลารอการล็อค" หลังจากนั้นประมาณ 50 วินาที สิ่งนี้ไม่น่าประหลาดใจนักเนื่องจากคอลัมน์แถวไม่ได้จัดทำดัชนี

อย่างไรก็ตามฉันทำSELECT id FROM table WHERE email='invalid address'และใช้เวลา 1.25 วินาที วิ่งDELETE FROM table WHERE id in (...)คัดลอกรหัสจากผลลัพธ์ SELECT ใช้เวลา 0.02 วินาที

เกิดอะไรขึ้น? ใครสามารถอธิบายได้ว่าเหตุใด DELETE ที่มีเงื่อนไขจึงช้าลงจนหมดเวลา แต่การเลือก SELECT จากนั้นการลบด้วย id นั้นเร็วมาก

ขอบคุณ

แก้ไข:ตามคำขอฉันโพสต์โครงสร้างตารางเช่นเดียวกับexplainผลลัพธ์บางอย่าง ฉันควรทราบด้วยว่าไม่มีคีย์ต่างประเทศที่อ้างถึงตารางนี้

อย่างไรก็ตามสถานการณ์ดูเหมือนจะตรงไปตรงมากับฉัน: ฉันมีเขตข้อมูลที่ไม่ได้ดัชนีที่ฉันเลือกกับ ต้องใช้การสแกนทั้งโต๊ะ แต่มันก็ไม่ใหญ่มาก idเป็นคีย์หลักดังนั้นการลบโดย id จะเร็วมากอย่างที่ควรจะเป็น

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)

2
ฉันเดาว่าคุณต้องโพสต์SHOW CREATE TABLEและอาจจะEXPLAIN...เกินไป
Radu Murzea

@SoboLAN จริงเหรอ? ดูเหมือนว่าจะเป็นสถานการณ์ง่าย ๆ ฉันอัพเดทคำถาม
itsadok

ใช่ แต่ .... คุณพูดถูกตั้งแต่แรก หากฟิลด์emailยังไม่ทำดัชนีให้ทำทั้งสองอย่างDELETEและSELECTทำงานช้าพอ ๆ กัน หรือ: คุณบอกว่าตารางมีการสอบถามอย่างหนัก บางทีเมื่อคุณลองครั้งแรกของคุณDELETEอาจมีใครบางคนกำลังทำธุรกรรมที่ยาวมาก ๆ ในแถวเหล่านั้น ...
Radu Murzea

อีกคำอธิบายของDELETE FROM ThreadNotification2 WHERE email='invalid address';อาจจะช่วยด้วย ...
pconcepcion

@pconcepcion ถ้าคุณเขียนEXPLAIN DELETE FROM....มันจะไม่ทำงาน จากสิ่งที่ฉันรู้มันใช้ได้เฉพาะในSELECTs
Radu Murzea

คำตอบ:


6

หากฟิลด์emailยังไม่ทำดัชนีให้ทำทั้งสองอย่างDELETEและSELECTทำงานช้าพอ ๆ กัน

ความเป็นไปได้เพียงอย่างเดียวที่ฉันนึกได้คือคุณพูดว่าตารางนั้นมีการเข้าถึงอย่างหนัก อาจจะมีคนอื่นวิ่งการทำธุรกรรมที่ยาวมาก (ที่เกี่ยวข้องโดยตรงหรือโดยอ้อมแถวเฉพาะเหล่านั้น) DELETEในขณะที่คุณกำลังพยายามที่จะดำเนินการ

ฉันคิดว่าบางทีคุณควรแทรกแถวจำลองไว้ที่นั่นแล้วลองลบออก ทำอย่างนั้น 2 หรือ 3 ครั้ง หากมีความแตกต่างใหญ่ในระยะเวลาของการDELETEโหลดฐานข้อมูลอาจเป็นเหตุผล

PS: ทำอย่างนั้นก็ต่อเมื่อผู้คนจะไม่รำคาญกับแถวจำลองเหล่านั้น: D


2
คำตอบของคุณคือ "ฉันไม่รู้ว่าทำไม"
Pacerier
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.