MySQL中 in 和 exists 的区别

2022-10-10 14:09:36

目录

EXISTS

IN

总结

参考


为什么说MySQL中,外表大用in,内表大用exists?

EXISTS

exists表示存在,它常常和子查询配合使用

  • exists对外表用loop逐条查询,每次查询都会查看exists的条件语句
  • 当子查询返回为真时,则外层查询语句将进行查询,否则外层查询将不进行查询或者返回空的记录。

看一个栗子:

select * from t1 where exists (select null from t2 where b = a )

可以理解为:

for x in ( select * from t1 )
loop
   if ( exists ( select null from t2 where t2.b = x.a ))
   then
      OUTPUT THE RECORD!
   end if
end loop

    可以看到外表是要拿全部的记录的,这个循环次数就取决于外表的记录数,就是说外表  t1 它不能很大
    而判断条件中,如果 t2 中相应字段有索引,那么 t2 大些是没关系的,因为去 t2 中根据条件查的时候是会走索引的。
    最后的结果集也就是符合条件的所有记录。

    例如, t1 有 100 条记录,t2(子查询结果集) 有 10000 条记录,那么上述循环最多操作 100 次。
    反过来则需要循环10000 次,性能上就不用多说了。

IN

  • in 子查询的条件返回结果只能是一个字段
  • in() 语句只会执行一次,会将符合子查询条件的记录全都查出来,假设结果集为B,共有 m 条记录并且缓存起来,然后在将子查询条件的结果集分解成 m 个,再进行 m 次查询

一个栗子:

select * from t1 where a in ( select b from t2 )

可以理解为先执行 in 中的查询:select b from t2,然后select * from t1,接着 where t1.a = t2.b

即:

select * from t1,(select b from t2) t2 where t1.a = t2.b;

从这个语句可以知道 t2绝对不能是个大表,但是 t1 可以很大,为什么呢?

最通俗的理解就是因为 t1.a = t2.b可以走索引。
但这并不是一个很好的解释,试想,如果 t1.a 和 t2.b 都有索引,索引是种有序的结构,因此 t1 和 t2 之间最佳的方案是走 merge join。

再来换个理解方式:首先从 t2 表中查询出来的数据会被缓存起来,然后遍历 t1 表,查看 t1 的字段 a 是否存在于缓存。

伪代码:

int[] bColumns = query("select b from t2");
Object[] aRows = queryObjs("select * from t1");
ArrayList<Object> res = new ArrayList();
    
for(int id : bColumns) {
    for(Object row : aRows) {
        if(row.a == id) {
            res.add(row);
        }
    }
}

把外层可以计算的尽可能放到外层,减少在内层的运算,有判断条件的语句和与循环不相关的操作语句尽量放在 for 外面;
应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨切循环层的次数;

假如说你 t2(子查询结果集) 的数据量特别大,t1 数据量比较小,这时候是效率低的,
反过来,t1的数据量大,长循环在最内层,这时候效率是高的
10000 做 100次相加操作 和 100 做 10000次相加操作,自然是前者更高效啦。

另外,如果 t2.b 上有索引,对 t2 的排序性能也有很大提高。

总结

  1. IN 查询在内部表和外部表上都可以使用到索引。
  2. Exists 查询仅在内部表上可以使用到索引。
  3. 当子查询结果集很大,而外部表较小的时候,Exists 的 Block Nested Loop(Block 嵌套循环)的作用开始显现,并弥补外部表无法用到索引的缺陷,查询效率会优于IN。
  4. 当子查询结果集较小,而外部表很大的时候,Exists 的 Block嵌套循环优化效果不明显,IN 的外表索引优势占主要作用,此时IN的查询效率会优于Exists。
  5. 表的规模不是看内部表和外部表,而是外部表和子查询结果集。

参考

https://blog.csdn.net/jinjiniao1/article/details/92666614

https://www.dazhuanlan.com/2019/11/04/5dbfb136b3509/

https://www.xuebuyuan.com/183477.html

  • 作者:emmm苏星河
  • 原文链接:https://blog.csdn.net/fellhair/article/details/108359520
    更新时间:2022-10-10 14:09:36