Mysql 中 exists 和 in 的区别[java教程]

Mysql 中 exists 和 in 的区别

Mysqlexistsin 的区别[java教程]

最近刷到面试题:Mysqlexistsin 的区别,先说下答案。

下面将主查询的表称为外表;子查询的表称为内表。existsin 的区别如下:

  • 子查询使用 exists,会先进行主查询,将查询到的每行数据循环带入子查询校验是否存在,过滤出整体的返回数据;子查询使用 in,会先进行子查询获取结果集,然后主查询匹配子查询的结果集,返回数据
  • 外表内表相对大小情况不一样时,查询效率不一样:两表大小相当,in 和 exists 差别不大;内表大,用 exists 效率较高;内表小,用 in 效率较高。
  • 不管外表与内表的大小,not exists 的效率一般要高于 not in,跟子查询的索引访问类型有关。

建表、造数据,验证一下以上答案。

  1. # 建表 student1
  2. drop table if exists student1;
  3. create table student1(
  4. sid int primary key auto_increment,
  5. sname varchar(40)
  6. );
  7. # 建存储过程给表 student1,插入1000条数据
  8. drop procedure if exists addStudent1;
  9. create procedure addStudent1()
  10. BEGIN
  11. declare idx int;
  12. set idx = 1;
  13. while idx <= 1000 DO
  14. insert into student1 values(null, concat('student-', idx));
  15. set idx = idx + 1;
  16. end while;
  17. end;
  18. call addStudent1();
  19. select * from student1;
  20. # 建表 student2
  21. drop table if exists student2;
  22. create table student2(
  23. sid int primary key auto_increment,
  24. sname varchar(40)
  25. );
  26. # 建存储过程给表 student2,插入100000条数据
  27. drop procedure if exists addStudent2;
  28. create procedure addStudent2()
  29. BEGIN
  30. declare idx int;
  31. set idx = 1;
  32. while idx <= 100000 DO
  33. insert into student2 values(null, concat('student-', idx));
  34. set idx = idx + 1;
  35. end while;
  36. end;
  37. call addStudent2();
  38. select * from student2;

in 与 exists 的查询 SQL

  1. select count(1) from student1 where sname in (select sname from student2);
  2. select count(1) from student1 where exists (select sname from student2 where student2.sname = student1.sname);
  3. select count(1) from student2 where sname in (select sname from student1);
  4. select count(1) from student2 where exists (select sname from student1 where student2.sname = student1.sname);

执行时间:

  1. [SQL] select count(1) from student1 where sname in (select sname from student2);
  2. 受影响的行: 0
  3. 时间: 0.092s
  4. [SQL]
  5. select count(1) from student1 where exists (select sname from student2 where student2.sname = student1.sname);
  6. 受影响的行: 0
  7. 时间: 0.076s
  8. [SQL]
  9. select count(1) from student2 where sname in (select sname from student1);
  10. 受影响的行: 0
  11. 时间: 14.820s
  12. [SQL]
  13. select count(1) from student2 where exists (select sname from student1 where student2.sname = student1.sname);
  14. 受影响的行: 0
  15. 时间: 15.144s

结论:student2 大表在内适用 exists,所以第 2 条 SQL 比第 1 条快;student1 小表在内适用 in,所以第 3 条 SQL 比第 4 条快。

not in 与 not exists 的查询 SQL

  1. select count(1) from student1 where sname not in (select sname from student2);
  2. select count(1) from student1 where not exists (select sname from student2 where student2.sname = student1.sname);
  3. select count(1) from student2 where sname not in (select sname from student1);
  4. select count(1) from student2 where not exists (select sname from student1 where student2.sname = student1.sname);

执行时间:

  1. [SQL]
  2. select count(1) from student1 where sname not in (select sname from student2);
  3. 受影响的行: 0
  4. 时间: 0.079s
  5. [SQL]
  6. select count(1) from student1 where not exists (select sname from student2 where student2.sname = student1.sname);
  7. 受影响的行: 0
  8. 时间: 0.075s
  9. [SQL] select count(1) from student2 where sname not in (select sname from student1);
  10. 受影响的行: 0
  11. 时间: 15.797s
  12. [SQL]
  13. select count(1) from student2 where not exists (select sname from student1 where student2.sname = student1.sname);
  14. 受影响的行: 0
  15. 时间: 15.160s

结论:not exists 性能高于 not in

给 student1、student2 sname 字段,加上索引,上述结论仍然成立。

  1. create index idx_1 on student1(sname);
  2. create index idx_2 on student2(sname);

执行时间:

  1. [SQL] select count(1) from student1 where sname in (select sname from student2);
  2. 受影响的行: 0
  3. 时间: 0.022s
  4. [SQL]
  5. select count(1) from student1 where exists (select sname from student2 where student2.sname = student1.sname);
  6. 受影响的行: 0
  7. 时间: 0.014s
  8. [SQL]
  9. select count(1) from student2 where sname in (select sname from student1);
  10. 受影响的行: 0
  11. 时间: 0.379s
  12. [SQL]
  13. select count(1) from student2 where exists (select sname from student1 where student2.sname = student1.sname);
  14. 受影响的行: 0
  15. 时间: 0.373s
  16. [SQL]
  17. select count(1) from student1 where sname not in (select sname from student2);
  18. 受影响的行: 0
  19. 时间: 0.006s
  20. [SQL]
  21. select count(1) from student1 where not exists (select sname from student2 where student2.sname = student1.sname);
  22. 受影响的行: 0
  23. 时间: 0.006s
  24. [SQL]
  25. select count(1) from student2 where sname not in (select sname from student1);
  26. 受影响的行: 0
  27. 时间: 0.455s
  28. [SQL]
  29. select count(1) from student2 where not exists (select sname from student1 where student2.sname = student1.sname);
  30. 受影响的行: 0
  31. 时间: 0.418s

再细看一下,not in 与 not exists 查询索引使用情况

not in,子查询使用了 index_subquery 访问类型

  1. EXPLAIN EXTENDED select count(1) from student2 where sname not in (select sname from student1);
  2. SHOW WARNINGS;

Mysql 中 exists 和 in 的区别[java教程]-度崩网-几度崩溃

not exists,子查询使用了 ref 访问类型

  1. EXPLAIN EXTENDED select count(1) from student2 where not exists (select sname from student1 where student2.sname = student1.sname);
  2. SHOW WARNINGS;

Mysql 中 exists 和 in 的区别[java教程]-度崩网-几度崩溃

 

Java

@Transactional 注解哪些情况下会失效?[java教程]

2020-7-31 11:06:46

Java

图灵Java架构师学习路线图[java教程]

2020-8-24 21:06:26

本站所发布的一切源码、模板、应用等文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权。本站内容适用于DMCA政策。若您的权利被侵害,请与我们联系处理,站长 QQ: 84087680 或 点击右侧 私信:盾给网 反馈,我们将尽快处理。
⚠️
本站所发布的一切源码、模板、应用等文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权。本站内容适用于DMCA政策
若您的权利被侵害,请与我们联系处理,站长 QQ: 84087680 或 点击右侧 私信:盾给网 反馈,我们将尽快处理。
0 条回复 A文章作者 M管理员
欢迎您,新朋友,感谢参与互动!
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
私信列表
搜索