DELETE가 SELECT보다 너무 느린 이유는 무엇입니까?


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 결과에서 ID를 복사하여 붙여 넣는 데 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인덱싱되지 않은되고, 다음 모두 DELETESELECT동등하게 느린 작동합니다. 또는 : 당신은 테이블이 심하게 쿼리된다고 말합니다. 어쩌면 당신이 처음 시도했을 때 DELETE누군가가 그 행에서 정말 긴 거래를 실행 했을 수도 있습니다 ...
Radu Murzea

또 다른 설명 DELETE FROM ThreadNotification2 WHERE email='invalid address';도 도움 이 될 것입니다 ...
pconcepcion

@pconcepcion을 쓰면 EXPLAIN DELETE FROM....작동하지 않습니다. 내가 아는 바로는 SELECTs 에서만 작동합니다 .
Radu Murzea

답변:


6

필드가있는 경우 email인덱싱되지 않은되고, 다음 모두 DELETESELECT동등하게 느린 작동합니다.

내가 생각할 수있는 유일한 가능성은 다음과 같습니다. 테이블에 많이 액세스했다고 말합니다. 어쩌면 누군가 실행하려고하는 동안 누군가가 매우 긴 트랜잭션을 실행했습니다 (직접적으로 또는 간접적으로 특정 행 포함) DELETE.

어쩌면 거기에 모의 행을 삽입하고 삭제하려고해야한다고 생각합니다. 두세 번하세요. 의 지속 시간에 큰 차이가 있으면 DELETEDB로드가 원인 일 수 있습니다.

추신 : 사람들이 모의 행에 짜증을 내지 않을 경우에만 그렇게하십시오 : D.


2
당신의 대답은 "왜 그런지 모르겠다"입니까?
Pacerier
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.