MySQL性能優化-in和exists


一直聽說exists性能比in快,但為啥快,一直不明白,乘着今天重點研究mysql,看到底是不是這么回事,原因又是在哪里。

1、我們先准備2張表和數據,人員表插入100W條數據,部門表插入5條數據。

DROP TABLE IF EXISTS `bd_dept`;
CREATE TABLE `bd_dept`  (
  `id` int(0) NOT NULL,
  `dept_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '部門名稱',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '部門' ROW_FORMAT = Dynamic;

DROP TABLE IF EXISTS `bd_user`;
CREATE TABLE `bd_user`  (
  `id` bigint(0) NOT NULL,
  `dept_id` int(0) NULL DEFAULT NULL COMMENT '部門ID',
  `user_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用戶名稱',PRIMARY KEY (`id`) USING BTREE,INDEX `dept_id`(`dept_id`) USING BTREE,
  CONSTRAINT `bd_user_ibfk_1` FOREIGN KEY (`dept_id`) REFERENCES `bd_dept` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '人員' ROW_FORMAT = DYNAMIC;

2、我們測試一下結果

  1)根據部門名稱找所有該部門下的人員信息:

select * from bd_user a where exists (select 1 from bd_dept b where b.dept_name='研發中心' and b.id=a.dept_id)
> OK
> Time: 0.814s

select * from bd_user a where a.dept_id in (select id from bd_dept b where b.dept_name='研發中心')
> OK
> Time: 0.8s

  從結果上看,in和exists查詢效率基本一致,多次執行執行查詢,看不出來誰快誰慢。我們看下他們的執行計划:

mysql> explain select * from bd_user a where exists (select 1 from bd_dept b where b.dept_name='研發中心' and b.id=a.dept_id); +----+-------------+-------+------------+------+---------------+---------+---------+---------------+--------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+---------+---------+---------------+--------+----------+-------------+ | 1 | SIMPLE | b | NULL | ALL | PRIMARY | NULL | NULL | NULL | 4 | 25.00 | Using where | | 1 | SIMPLE | a | NULL | ref | dept_id | dept_id | 5 | zhi_test.b.id | 332010 | 100.00 | NULL | +----+-------------+-------+------------+------+---------------+---------+---------+---------------+--------+----------+-------------+
mysql> explain select * from bd_user a where a.dept_id in (select id from bd_dept b where b.dept_name='研發中心'); +----+-------------+-------+------------+------+---------------+---------+---------+---------------+--------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+---------+---------+---------------+--------+----------+-------------+ | 1 | SIMPLE | b | NULL | ALL | PRIMARY | NULL | NULL | NULL | 4 | 25.00 | Using where | | 1 | SIMPLE | a | NULL | ref | dept_id | dept_id | 5 | zhi_test.b.id | 332010 | 100.00 | NULL | +----+-------------+-------+------------+------+---------------+---------+---------+---------------+--------+----------+-------------+

  他們的執行計划完全相同。

  2)根據人員名稱找他所在部門的信息:

select * from bd_dept a where exists (select 1 from bd_user b where b.user_name='測試0000000031' and a.id=b.dept_id)
> OK
> Time: 0.19s

select * from bd_dept a where a.id in (select b.dept_id from bd_user b where b.user_name='測試0000000031')
> OK
> Time: 0.19s

  從結果上看in和exists效率還是一樣的,我們再看看執行計划

mysql> explain select * from bd_dept a where exists (select 1 from bd_user b where b.user_name='測試0000000031' and a.id=b.dept_id);
+----+--------------+-------------+------------+--------+---------------------+---------------------+---------+---------------+--------+----------+-------------+
| id | select_type  | table       | partitions | type   | possible_keys       | key                 | key_len | ref           | rows   | filtered | Extra       |
+----+--------------+-------------+------------+--------+---------------------+---------------------+---------+---------------+--------+----------+-------------+
|  1 | SIMPLE       | a           | NULL       | ALL    | PRIMARY             | NULL                | NULL    | NULL          |      4 |   100.00 | Using where |
|  1 | SIMPLE       | <subquery2> | NULL       | eq_ref | <auto_distinct_key> | <auto_distinct_key> | 5       | zhi_test.a.id |      1 |   100.00 | NULL        |
|  2 | MATERIALIZED | b           | NULL       | ALL    | dept_id             | NULL                | NULL    | NULL          | 996030 |    10.00 | Using where |
+----+--------------+-------------+------------+--------+---------------------+---------------------+---------+---------------+--------+----------+-------------+
mysql> explain select * from bd_dept a where a.id in (select b.dept_id from bd_user b where b.user_name='測試0000000031');
+----+--------------+-------------+------------+--------+---------------------+---------------------+---------+---------------+--------+----------+-------------+
| id | select_type  | table       | partitions | type   | possible_keys       | key                 | key_len | ref           | rows   | filtered | Extra       |
+----+--------------+-------------+------------+--------+---------------------+---------------------+---------+---------------+--------+----------+-------------+
|  1 | SIMPLE       | a           | NULL       | ALL    | PRIMARY             | NULL                | NULL    | NULL          |      4 |   100.00 | Using where |
|  1 | SIMPLE       | <subquery2> | NULL       | eq_ref | <auto_distinct_key> | <auto_distinct_key> | 5       | zhi_test.a.id |      1 |   100.00 | NULL        |
|  2 | MATERIALIZED | b           | NULL       | ALL    | dept_id             | NULL                | NULL    | NULL          | 996030 |    10.00 | Using where |
+----+--------------+-------------+------------+--------+---------------------+---------------------+---------+---------------+--------+----------+-------------+

  這2個SQL的執行計划也完全相同。

3、結論

  實踐出真知,in和exists的性能在MySQL8.x中是一樣的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM