ORACLE中in语句与exists语句的区别

我看了这篇文章对于笛卡尔积的认识更深入了,感觉sql语句的执行过程和算法分析中的分析时间复杂度的过程很像。因此特意转载一下,感谢写作本文的大神。

select * from a

where id in(select id from b)

以上查询使用了in语句,in()只执行一次,它查出b表中的所有id字段并缓存起来.之后,检查a表的id是否与b表中的id相等,如果相等则将a表的记录加入结果集中,直到遍历完a表的所有记录.

它的查询过程类似于以下过程
list resultset=[];
array a=(select * from a);
array b=(select id from b);

for(int i=0;i < a.length;i++) {
  for(int j=0;j < b.length;j++) {
   if(a[i].id==b[j].id) {
    resultset.add(a[i]);
     break;
  }
 }
}
return resultset;
 

可以看出,当b表数据较大时不适合使用in(),因为它会b表数据全部遍历一次.

如:a表有10000条记录,b表有1000000条记录,那么最多有可能遍历10000*1000000次,效率很差.

再如:a表有10000条记录,b表有100条记录,那么最多有可能遍历10000*100次,遍历次数大大减少,效率大大提升.

结论:in()适合b表比a表数据小的情况

select a.* from a a

where exists(select 1 from b b where a.id=b.id)

以上查询使用了exists语句,exists()会执行a.length次,它并不缓存exists()结果集,因为exists()结果集的内容并不重要,重要的是结果集中是否有记录,如果有则返回true,没有则返回false.

它的查询过程类似于以下过程

list resultset=[];

array a=(select * from a)

for(int i=0;i < a.length;i++) {
  if(exists(a[i].id) { //执行select 1 from b b where b.id=a.id是否有记录返回
    resultset.add(a[i]);
   }
}

return resultset;

当b表比a表数据大时适合使用exists(),因为它没有那么遍历操作,只需要再执行一次查询就行.

如:a表有10000条记录,b表有1000000条记录,那么exists()会执行10000次去判断a表中的id是否与b表中的id相等.

如:a表有10000条记录,b表有100000000条记录,那么exists()还是执行10000次,因为它只执行a.length次,可见b表数据越多,越适合exists()发挥效果.

再如:a表有10000条记录,b表有100条记录,那么exists()还是执行10000次,还不如使用in()遍历10000*100次,因为in()是在内存里遍历比较,而exists()需要查询,我们都知道查询数据库所消耗的性能更高,而内存比较很快.

结论:exists()适合b表比a表数据大的情况

当a表数据与b表数据一样大时,in与exists效率差不多,可任选一个使用.

(0)
上一篇 2022年3月22日
下一篇 2022年3月22日

相关推荐