Tengo una tabla InnoDB bastante ocupada (200,000 filas, supongo que algo así como decenas de consultas por segundo). Debido a un error, obtuve 14 filas con (la misma) direcciones de correo electrónico no válidas y quería eliminarlas.
Simplemente intenté DELETE FROM table WHERE email='invalid address'
y obtuve el "Tiempo de espera de bloqueo excedido" después de unos 50 segundos. Esto no es terriblemente sorprendente, ya que la columna de la fila no está indexada.
Sin embargo, luego lo hice SELECT id FROM table WHERE email='invalid address'
y eso tomó 1.25 segundos. Ejecutar DELETE FROM table WHERE id in (...)
, copiar y pegar los identificadores del resultado SELECCIONAR, tomó 0.02 segundos.
Que esta pasando? ¿Alguien puede explicar por qué ELIMINAR con la condición es tan lento que agota el tiempo de espera, pero hacer SELECCIONAR y luego eliminar por id es tan rápido?
Gracias.
EDITAR: Por solicitud, publiqué la estructura de la tabla y algunos explain
resultados. También debo tener en cuenta que no hay claves foráneas que se refieran a esta tabla.
Sin embargo, la situación me parece sencilla: tengo un campo no indexado con el que estoy seleccionando. Esto requiere escanear toda la tabla, pero no es terriblemente grande. id
es la clave principal, por lo que eliminar por id es muy rápido, como debería ser.
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)
fuente
SHOW CREATE TABLE
y probablemente unEXPLAIN...
también.email
es no indexados, entonces ambosDELETE
ySELECT
debería funcionar igualmente lento. O bien: Usted dice que la mesa está muy consultada. Tal vez cuandoDELETE
DELETE FROM ThreadNotification2 WHERE email='invalid address';
quizás ayudaría también ...EXPLAIN DELETE FROM....
, no funcionará. Por lo que sé, funciona solo enSELECT
s.Respuestas:
Si el campo
email
es no indexados, entonces ambosDELETE
ySELECT
debería funcionar igualmente lento.La única posibilidad que se me ocurre es: usted dice que se accede mucho a la tabla. Tal vez alguien más ejecutó una transacción muy larga (que involucra directa o indirectamente esas filas específicas) mientras intentaba ejecutar el
DELETE
.Creo que tal vez deberías insertar algunas filas simuladas allí e intentar eliminarlas. Haz eso 2 o 3 veces. Si hay una gran diferencia en la duración de la
DELETE
, entonces la carga de DB es probablemente la razón.PD: Haz eso solo si las personas no se molestarán por esas filas simuladas: D.
fuente