轉載自https://blog.csdn.net/a_hui_tai_lang/article/details/81146635
1.系統要求進行SQL優化,對效率比較低的SQL進行優化,使其運作效率更高,其中要求對SQL中的部分in/not in修改為exists/not exists
2.分析一下exists真的就比in的效率高嗎?
我們先讨論IN和EXISTS。
select from t1 where x in ( select y from t2 )
事實上可以了解為:
select
from t1, ( select distinct y from t2 ) t2
where t1.x = t2.y;
——如果你有一定的SQL優化經驗,從這句很自然的可以想到t2絕對不能是個大表,因為需要對t2進行全表的“唯一排序”,如果t2很大這個排序的性能是不可忍受的。但是t1可以很大,為什麼呢?最通俗的了解就是因為t1.x=t2.y可以走索引。但這并不是一個很好的解釋。試想,如果t1.x和t2.y都有索引,我們知道索引是種有序的結構,是以t1和t2之間最佳的方案是走merge join。另外,如果t2.y上有索引,對t2的排序性能也有很大提高。
select from t1 where exists ( select null from t2 where y = x )
可以了解為:
for x in ( select from t1 )
loop
if ( exists ( select null from t2 where y = x.x )
then
OUTPUT THE RECORD!
end if
end loop
——這個更容易了解,t1永遠是個表掃描!是以t1絕對不能是個大表,而t2可以很大,因為y=x.x可以走t2.y的索引。
綜合以上對IN/EXISTS的讨論,我們可以得出一個基本通用的結論:IN适合于外表大而内表小的情況;EXISTS适合于外表小而内表大的情況。**
繼續分析
in 是把外表和内表作hash 連接配接,而exists是對外表作loop循環,每次loop循環再對内表進行查詢。*
一直以來認為exists比in效率高的說法是不準确的。
如果查詢的兩個表大小相當,那麼用in和exists差别不大。
如果兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in:
例如:表A(小表),表B(大表)
1:
select from A where cc in (select cc from B)
效率低,用到了A表上cc列的索引;
select from A where exists(select cc from B where cc=A.cc)
效率高,用到了B表上cc列的索引。
相反的
2:
select from B where cc in (select cc from A)
效率高,用到了B表上cc列的索引;
select from B where exists(select cc from A where cc=B.cc)
效率低,用到了A表上cc列的索引。
3.not in 和not exists
如果查詢語句使用了not in 那麼内外表都進行全表掃描,沒有用到索引;
而not extsts 的子查詢依然能用到表上的索引。
是以無論那個表大,用not exists都比not in要快。