無論是做項目還是普通使用SQL,我們通常都會使用IN。因為很好理解,也很方便。但是,面對著多層查詢嵌套,或者IN關鍵字裡面的結果集數量巨大,查詢的效率就會直線下降。這時候,我們應該用好EXSITS。
首先,來一個簡單的例子。
with score(id,name,subject,score) as( select 0,'張三','數學',88 from dual union all select 1,'張三','英語',78 from dual union all select 2,'李四','數學',68 from dual union all select 3,'李四','英語',98 from dual union all select 4,'王五','數學',77 from dual union all select 5,'王五','英語',92 from dual union all select 6,'趙六','數學',81 from dual union all select 7,'趙六','英語',75 from dual ) ,has_phone(name,has_phone) as( select '張三','有' from dual union all select '李四','沒有' from dual union all select '王五','沒有' from dual union all select '趙六','有' from dual ) --select * -- from score a -- where name in (select name from has_phone where has_phone = '有') select * from score a where exists (select 1 from has_phone b where b.name = a.name and has_phone = '有')
這段SQL的意思是,查詢有手機的同學的成績。
那麼我來理解一下IN和EXSITS的區別吧。
在使用IN的時候。
數據庫首先是去在has_phone裡面查找所有條件為“有”的name。
然後把這些結果集讓每一個name去匹配。
在使用EXSITS的時候。
數據庫是先查詢SCORE,然後每個連接條件到EXSITS裡面進行判斷。
如果為TRUE,則加入結果集,否則就跳過。
EXSITS執行過程
可以理解為:
for x in (select * from score a)
loop
if(exists(select 1 from has_phone b where b.name = a.name ))
then
output the record;
end if;
end loop;
對於in 和 exists的性能區別:
如果子查詢得出的結果集記錄較少,主查詢中的表較大且又有索引時應該用in;
反之如果外層的主查詢記錄較少,子查詢中的表大,又有索引時使用exists.
其實我們區分in和exists主要是造成了驅動順序的改變(這是性能變化的關鍵),如果是exists,
那麼以外層表為驅動表,先被訪問,如果是IN,那麼先執行子查詢,所以我們會以驅動表的快速返回為目標,
那麼就會考慮到索引及結果集的關系了
原文:http://dacoolbaby.iteye.com/blog/1638990