一般在做SQL優化的時候講究使用exists帶替代IN的做法,理由是EXISTS執行效率要比IN高。
個人理解:
IN表示範圍,指某一字段在某一範圍之内,這個範圍一般使用子查詢來獲取,由此可知IN子查詢返回的結果應該就是這個範圍集。
EXISTS表示存在,指至少存在一處,這個條件由EXISTS子查詢來完成,但是在這裡EXISTS子查詢返回的結果卻不再是一個結果集,而是一個布爾值(true或false),其實這個挺好理解的,EXISTS就表示如果子查詢能查到值則返回true,則執行EXISTS之前的語句。
員工參數課程培訓數據,兩次不同課程培訓分别存在CLASS_A 和 CLASS_B 兩張表中。
CLASS_A:
CLASS_B:
需求:查找同時參加了兩門課程的員工。
下面分别使用in 和 exists兩種方式實現。
1、in 方式查詢
SELECT * FROM class_a WHERE id IN ( SELECT id FROM class_b);
2、exists 方式查詢
SELECT * FROM class_a A WHERE EXISTS ( SELECT * FROM class_b B WHERE A.id = B.id );
說明:
上述兩種方法查詢結果一樣,但exists 方式速度要快。分析如下:
1)如果連接列id 上有索引,那麼查詢CLASS_B時,無需查詢實際表,僅需要查索引就可以了。
2)使用exists ,那麼隻有查到一行數據滿足條件就會終止查詢,不會産生臨時表。
3)使用in查詢時,數據庫首先會執行子查詢,然後将結果保存在臨時表中,然後掃描整個臨時表,很多情況下非常耗費資源。
假如有一個表user,它有兩個字段id和name,要查詢名字中帶a的用戶信息:
最簡單的SQL:select * from user where name like '%a%'; 使用IN的SQL:select u.* from user u where u.id in (select uu.id from user uu where uu.name like '%a%');
将使用IN的SQL修改為使用EXISTS的SQL該怎麼寫呢?
一開始我直接将u.id in 替換為EXISTS,獲得如下語句 :
select u.* from user u where exists(select uu.id from user uu where uu.name like '%a%');
經過測試發現輸出結果錯誤,該語句将所有的用戶全部一個不漏的查詢出來了,相信你也發現了問題,後來我對上述語句做了修改如下:
select u.* from user u where exists (select uu.id from user uu where uu.name like '%a%' and uu.id=u.id);
隻是在子查詢中添加了“and uu.id=u.id”,結果查詢結果正确。
總結:EXISTS子查詢可以看成是一個獨立的查詢系統,隻為了獲取真假邏輯值,EXISTS子查詢與外查詢查詢的表是兩個完全獨立的毫無關系的表(當第二個表中的name中有包含a的姓名存在,那麼就執行在第一個表中查詢所有用戶的操作),當我們在子查詢中添加了id關聯之後,EXISTS子查詢與外查詢查詢的表就統一了,是二者組合組建的虛表,是同一個表(這樣當子查詢查詢到虛表中當前行的uu.name中包含a時,則将虛表當前行中對應的u.id與u.name查詢到了)
所以一切的重點就在這個ID關聯之上,添加ID關聯,數據庫會先将兩張表通過ID關聯組合成一張虛表,所有的查詢操作都在這張虛表上完成,操作的是同一張表,當然就不會出現之前的那種情況了!
exists 方式查詢 比 in 方式查詢效率高,但in 可讀性較好。建議盡可能使用exists方式,避免使用子查詢,除非in 的參數為數值列表。
後面會分享更多DBA方面内容,感興趣的朋友可以關注下!
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!