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)list和listB取笛卡爾積,即有 listA.len*listB.len 條記錄。根據 a.id=b.a_id 對笛卡爾積結果進行篩選。
for(t in 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 in listA.length){
if( (select 1 from tableB b where b.a_id=a.id) != null ) {
list.add(a);
}
}
所以,exists的效率取決於外查詢。
總結
當子查詢的結果集相對很大時,千萬不要用
所以,除非子in查詢結果集很小(比如字典),一般都優先使用exists(沒有in的笛卡爾積)。
not in 和 not exists
雖然“一般情況下,使用exists比使用in更好”的說法不一定準確,
但是“一般情況下,使用 not exists 比使用 not in 更好”的說法是沒問題的。
使用 not in 會對外表和內表進行全表掃描,會忽略掉索引;
使用not exists的子查詢可以使用表的索引的。
所以,無論子查詢結果集大小,使用 not exists 要比 not in 來的快。
參考:
https://www.cnblogs.com/liyasong/p/sql_in_exists.html
in和exists過程對比