zoukankan      html  css  js  c++  java
  • 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中是一样的。

  • 相关阅读:
    书本第十三章课后习题4、5、6
    软件工程一班第五小组知识树系统-软件测试计划
    第八周作业
    第七周作业——用面向对象方法分析研究书中习题2第3题中描述的机票预订系统,试建立它的对象模型、动态模型和功能模型。
    第六周作业——建立订货系统的用例模型
    第五周作业——用状态转换图描绘复印机的行为
    第四周作业——在你的实际项目旅游网站中,网页主页面主要有哪些模块?
    第三周作业—— 在软件开发的早期阶段为什么要进行可行性研究?应该从哪些方面研究目标系统的可行性?
    第二周作业——面向过程(或者叫结构化)分析方法与面向对象分析方法到底区别在哪里?请根据自己的理解简明扼要的回答。
    有学生提到,在大学选课的时候,可以写一个“刷课机”的程序,利用学校选课系统的弱点或漏洞,帮助某些人选到某些课程。或者帮助用户刷购票网站,先买到火车票。这些软件合法么?符合道德规范么?是在“软件工程”的研究范围么? 请大家讨论。
  • 原文地址:https://www.cnblogs.com/zhi-leaf/p/12806073.html
Copyright © 2011-2022 走看看