14

I have a fairly busy InnoDB table (200,000 rows, I guess something like tens of queries per second). Due to a bug I got 14 rows with (the same) invalid email addresses in them and wanted to delete them.

I simply tried DELETE FROM table WHERE email='invalid address' and got "Lock wait timeout exceeded" after about 50 seconds. This is not terribly surprising, since the row column is not indexed.

However, I then did SELECT id FROM table WHERE email='invalid address' and that took 1.25 seconds. Running DELETE FROM table WHERE id in (...), copy-pasting the ids from the SELECT result, took 0.02 seconds.

What is going on? Can someone explain why the DELETE with the condition is so slow that it times out, but doing SELECT and then deleting by id is so fast?

Thanks.

EDIT: By request, I posted the table structure as well as some explain results. I should also note that there are no foreign keys referring to this table.

However, the situation seems straightforward to me: I have an unindexed field that I'm selecting against. This requires scanning the whole table, but it's not terribly big. id is the primary key, so deleting by id is very quick, as it should be.

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)
8
  • 2
    I guess you absolutely must post a SHOW CREATE TABLE and probably an EXPLAIN... too. Commented Jul 25, 2012 at 6:22
  • @SoboLAN really? It's seems like such a simple scenario. I updated the question.
    – itsadok
    Commented Jul 25, 2012 at 7:19
  • Yeah but.... you were right in the first place. If the field email is unindexed, then both DELETE and SELECT should work equally slow. Or: You say that the table is queried heavily. Maybe when you tried your first DELETE there was someone else running a really long transaction on those rows... Commented Jul 25, 2012 at 7:22
  • Another explain of DELETE FROM ThreadNotification2 WHERE email='invalid address'; maybe would help also... Commented Jul 25, 2012 at 8:27
  • @pconcepcion if you write EXPLAIN DELETE FROM...., it won't work. From what I know, it works only on SELECTs. Commented Jul 25, 2012 at 8:29

1 Answer 1

7

If the field email is unindexed, then both DELETE and SELECT should work equally slow.

The only possibility I can think of is: You say that the table is heavily accessed. Maybe someone else ran a very long transaction (involving directly or indirectly those specific rows) while you were trying to execute the DELETE.

I think maybe you should insert some mock rows there and try to delete them. Do that 2 or 3 times. If there is a big difference in the duration of the DELETE, then the DB load is probably the reason.

PS: Do that only if people won't be annoyed by those mock rows :D .

2
  • 4
    So is your answer "I don't know why"?
    – Pacerier
    Commented Apr 9, 2015 at 5:10
  • When you say that a long transaction may lead to slower delete times, you mean it may take more time to acquire an exclusive lock on the rows, right? Commented Jul 8, 2020 at 20:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.