in和exists过程对比
两者执行流程完全不一样。
in的过程
select * from tableA a where a.id in (select b.a_id from tableB b);
1)首先子查询,查询B表中所有的 aid,结果集 listB。
2)进行外查询,结果集 listA。
3)listA 和 listB 取笛卡尔积,即有 listA.len*listB.len 条记录。根据 a.id=b.a_id 对笛卡尔积结果进行筛选。
for(t : listA.len*listB.len){
if(t.id == t.aid) {
list.add(t);
}
}
retrun list;
所以,in的效率取决于in子查询。
exists的过程
select * from tableA a where exists (select 1 from tableB b where a.id=b.a_id);
1)外查询,这里是select * from tableA a,结果集 listA。
2)对 listA 的 a.id 进行 exists 筛选。
for(a : listA.length){
if( (select 1 from tableB b where b.a_id=a.id) != null ) {
list.add(a);
}
}
retrun list;
所以,exists的效率取决于外查询.
总结
当子查询的结果集相对很大时,不要用 in, 避免笛卡尔积。
一般, 除非子查询结果集很小(比如字典),否则都优先使用exists ??.
not in 和 not exists
虽然“一般情况下,使用exists比使用in更好”的说法不一定准确,
但是“一般情况下,使用 not exists 比使用 not in 更好”的说法是没问题的。
使用 not in 会对外表和内表进行全表扫描,会忽略掉索引;
使用not exists的子查询可以使用表的索引的。
参考:
https://www.cnblogs.com/liyasong/p/sql_in_exists.html