Tôi có một bảng InnoDB khá bận rộn (200.000 hàng, tôi đoán có gì đó giống như hàng chục truy vấn mỗi giây). Do một lỗi, tôi có 14 hàng với (cùng) địa chỉ email không hợp lệ trong đó và muốn xóa chúng.
Tôi chỉ đơn giản là đã thử DELETE FROM table WHERE email='invalid address'
và nhận được "Khóa thời gian chờ vượt quá" sau khoảng 50 giây. Điều này không đáng ngạc nhiên lắm, vì cột hàng không được lập chỉ mục.
Tuy nhiên, sau đó tôi đã làm SELECT id FROM table WHERE email='invalid address'
và điều đó mất 1,25 giây. Chạy DELETE FROM table WHERE id in (...)
, dán sao chép id từ kết quả CHỌN, mất 0,02 giây.
Chuyện gì đang xảy ra vậy? Ai đó có thể giải thích lý do tại sao XÓA với điều kiện chậm đến mức hết thời gian không, nhưng thực hiện CHỌN và sau đó xóa bằng id quá nhanh?
Cảm ơn.
EDIT: Theo yêu cầu, tôi đã đăng cấu trúc bảng cũng như một số explain
kết quả. Tôi cũng cần lưu ý rằng không có khóa ngoại nào đề cập đến bảng này.
Tuy nhiên, tình huống có vẻ đơn giản với tôi: Tôi có một lĩnh vực chưa được tìm hiểu mà tôi đang chọn. Điều này đòi hỏi phải quét toàn bộ bảng, nhưng nó không quá lớn. id
là khóa chính, vì vậy việc xóa bằng id rất nhanh chóng.
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
được lập chỉ mục, thì cả hai DELETE
và SELECT
sẽ hoạt động chậm như nhau. Hoặc: Bạn nói rằng bảng được truy vấn rất nhiều. Có thể khi bạn thử lần đầu tiên, DELETE
có một người khác đang thực hiện một giao dịch thực sự dài trên các hàng đó ...
DELETE FROM ThreadNotification2 WHERE email='invalid address';
có lẽ cũng sẽ giúp ...
EXPLAIN DELETE FROM....
, nó sẽ không hoạt động. Từ những gì tôi biết, nó chỉ hoạt động trên SELECT
s.
SHOW CREATE TABLE
và có lẽ làEXPLAIN...
quá.