一、in 用法
in 語法為:
select *
from table_name
where col_name in (value1, value2,...);
in 操作符允許在 where 子句中規定多個值。
in 查詢相當於多個 or 條件的疊加,比較好理解。
in 查詢就是先將子查詢條件的記錄全都查出來。
in 查詢的子條件返回結果必須只有一個字段。
二、exists 用法
exists 語法為:
select *
from table_a a
where exists (select 1 from table_b b where b.id = b.id);
exists 對外表用 loop 逐條查詢,每次查詢都會查看 exists 的條件語句。
當 exists 里的條件語句能夠返回記錄行時(無論返回多少記錄行,只要能返回),條件就為真,返回當前 loop 到的這條記錄。
反之如果 exists 里的條件語句不能返回記錄行,則當前 loop 到的這條記錄被丟棄。
exists 的條件就像一個 bool 條件,當能返回結果集則為 true,不能返回結果集則為 false。
當子查詢為 select NULL 時, mysql 仍然認為它是 True。
三、in 與 exists 的區別
in 語句:只執行一次
確定給定的值是否與子查詢或列表中的值相匹配。
in 在查詢的時候,首先查詢子查詢的表,然后將內表和外表做一個笛卡爾積,然后按照條件進行篩選。
所以相對內表比較小的時候,in 的速度較快。
exists 語句:執行n次(外表行數)
指定一個子查詢,檢測行的存在。
遍歷循環外表,檢查外表中的記錄有沒有和內表的的數據一致的。
匹配得上就放入結果集。
區別和應用場景
in 和 exists 的區別: 如果子查詢得出的結果集記錄較少,主查詢中的表較大且又有索引時應該用 in, 反之如果外層的主查詢記錄較少,子查詢中的表大,又有索引時使用 exists。
其實我們區分 in 和 exists 主要是造成了驅動順序的改變(這是性能變化的關鍵),如果是 exists,那么以外層表為驅動表,先被訪問,如果是 in ,那么先執行子查詢,所以我們會以驅動表的快速返回為目標,那么就會考慮到索引及結果集的關系 ,另外 in 是不對 NULL 進行處理。
in 是把外表和內表作 hash 連接,而 exists 是對外表作 loop 循環,每次 loop 循環再對內表進行查詢。一直以來認為 exists 比 in 效率高的說法是不准確的。
not in 和 not exists
如果查詢語句使用 not in,那么內外表都進行全表掃描,沒有用到索引;
而 not exists 的子查詢依然能用到表上的索引。所以無論那個表大,用 not exists 都比not in 要快。
四、結論
1. 外層查詢表小於子查詢表,則用 exists,外層查詢表大於子查詢表,則用 in ,如果外層和子查詢表差不多,則愛用哪個用哪個。
2.not exists 比 not in 效率高。
in 的遍歷是在內存中遍歷。
而 exists 需要查詢數據庫。
查詢數據庫所消耗的性能更高,而內存比較快。
參考鏈接1:在MySQL里,有個和in一樣的東東叫做exists,但是它比in更牛叉,你會么?
