我是 MySQL 优化的新手,我发现了一个惊人的事情:带有 'exists' 的 sql 运行速度比使用 'in' 慢!!!
以下是我的 DDL:
mysql> `show create table order\G`;
*************************** 1. row ***************************
Table: order
Create Table: CREATE TABLE `order` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`employee_id` int(4) NOT NULL,
`price` decimal(7,2) NOT NULL,
`trade_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk_employee_id` (`employee_id`),
CONSTRAINT `fk_employee_id` FOREIGN KEY (`employee_id`) REFERENCES `employee` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=231001 DEFAULT CHARSET=utf8
mysql> `show create table order_detail\G`;
*************************** 1. row ***************************
Table: order_detail
Create Table: CREATE TABLE `order_detail` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`menu_id` int(4) NOT NULL,
`order_id` int(4) NOT NULL,
`amount` int(4) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_menu_id` (`menu_id`),
KEY `fk_order_id` (`order_id`),
CONSTRAINT `fk_menu_id` FOREIGN KEY (`menu_id`) REFERENCES `menu` (`id`),
CONSTRAINT `fk_order_id` FOREIGN KEY (`order_id`) REFERENCES `order` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1037992 DEFAULT CHARSET=utf8
Query Solution 1: use exists
---------------------------------
mysql> `SELECT count(`order`.id) FROM `order` WHERE EXISTS ( SELECT 1 FROM order_detail WHERE order_detail.order_id = `order`.id GROUP BY (order_detail.order_id) HAVING COUNT(order_id) > 5 );`
+-------------------+
| count(`order`.id) |
+-------------------+
| 92054 |
+-------------------+
1 row in set (***6.53 sec***)
mysql> `explain SELECT count(`order`.id) FROM `order` WHERE EXISTS ( SELECT 1 FROM order_detail WHERE order_detail.order_id = `order`.id GROUP BY (order_detail.order_id) HAVING COUNT(order_id) > 5 )\G;`
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: order
type: index
possible_keys: NULL
key: fk_employee_id
key_len: 4
ref: NULL
rows: 231032
Extra: Using where; Using index
*************************** 2. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: order_detail
type: ref
possible_keys: fk_order_id
key: fk_order_id
key_len: 4
ref: performance_test.order.id
rows: 3
Extra: Using where; Using index
2 rows in set (0.01 sec)
Query solution 2: use in
------------------------
mysql> `SELECT count(`order`.id) FROM `order` WHERE `order`.id IN ( SELECT order_detail.order_id FROM order_detail GROUP BY (order_detail.order_id) HAVING COUNT(order_id) > 5 ) ;`
+-------------------+
| count(`order`.id) |
+-------------------+
| 92054 |
+-------------------+
1 row in set (***3.88 sec***)
mysql> `explain SELECT count(`order`.id) FROM `order` WHERE `order`.id IN ( SELECT order_detail.order_id FROM order_detail GROUP BY (order_detail.order_id) HAVING COUNT(order_id) > 5 ) \G;`<br>
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: order
type: index
possible_keys: NULL
key: fk_employee_id
key_len: 4
ref: NULL
rows: 231032
Extra: Using where; Using index
*************************** 2. row ***************************
id: 2
select_type: SUBQUERY
table: order_detail
type: index
possible_keys: fk_order_id
key: fk_order_id
key_len: 4
ref: NULL
rows: 1036314
Extra: Using index
2 rows in set (0.00 sec)
最佳答案
我觉得你有点困惑,你有一个错误的想法,'EXISTS' 比 'IN' 工作得更快,我试图让你理解原因..
EXISTS 返回一个 bool 值,并将在第一次匹配时返回一个 bool 值。因此,如果您要处理重复项/多个项,根据数据和需求,“EXISTS”的执行速度将比“IN”或“JOIN”快。
而“IN”是 OR 子句的语法糖。虽然它非常方便,但在处理该比较的大量值(超过 1,000)时存在问题。在重复/倍数的情况下,“IN”会检查所有存在的值,这自然会比“EXISTS”消耗更多的执行时间,这就是为什么“IN”总是比“EXISTS”慢。
我希望我澄清了你的困惑。
关于mysql - 为什么带有 'exists' 的 sql 运行速度比使用 MySQL 的 'in' 慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20172487/