in和exists以及not in 和not exists有什么不同?(笔记)
生活随笔
收集整理的這篇文章主要介紹了
in和exists以及not in 和not exists有什么不同?(笔记)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
exists 和 in
1.原理
通過使用EXISTS,Oracle會首先檢查主查詢,然后運行子查詢直到它找到第一個匹配項,這就節省了時間。Oracle在執行IN子查詢時,首先執行子查詢,并將獲得的結果列表存放在一個加了索引的臨時表中。在執行子查詢之前,系統先將主查詢掛起,待子查詢執行完畢,存放在臨時表中以后再執行主查詢。這也就是使用EXISTS比使用IN通常查詢速度快的原因。2.分析
in 是把外表和內表作hash 連接,而exists是對外表作loop循環,每次loop循環再對內表進行查詢not exists:做NL,對子查詢先查,有個虛表,有確定值,所以就算子查詢有NULL最終也有值返回not in:做hash,對子查詢表建立內存數組,用外表匹配,那子查詢要是有NULL那外表沒的匹配最終無值返回。一直以來認為exists比in效率高的說法是不準確的。但是,如果查詢的兩個表大小相當,那么用in和exists差別不大。
3.總結
外表大,用IN;內表大,用EXISTS。4.效率
- select * from T1 where exists(select 1 from T2 where T1.a=T2.a) ;T1數據量小而T2數據量非常大時,T1<<T2 時,1) 的查詢效率高。 - select * from T1 where T1.a in (select T2.a from T2);T1數據量非常大而T2數據量小時,T1>>T2 時,2) 的查詢效率高。5.舉例說明
例如:表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列的索引。not in 和not exists
如果查詢語句使用了not in 那么內外表都進行全表掃描,沒有用到索引;而 not extsts的子查詢依然能用到表上的索引。 所以無論那個表大,用not exists都比not in要快。一直聽到的都是說盡量 用exists不要用in,因為exists只判斷存在而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;而使用existsselect * from t1 where exists ( select null from t2 where y = x ) 執行的過程相當于: for x in ( select * from t1 ) loopif ( exists ( select null from t2 where y = x.x )then OUTPUT THE RECORDend if end loopin的方式比較直觀,exists則有些繞,而且in可以用于各種子查詢,而exists好像 只用于關聯子查詢(其他子查詢當然也可以用,可惜沒意義)。 由于exists是用loop的 方式,所以,循環的次數對于exists影響最大,所以,外表要記錄數少,內表就無所謂了, 而in用的是hash join,所以內表如果小,整個查詢的范圍都會很小,如果內表很大,外表 如果也很大就很慢了,這時候exists才真正的會快過in的方式。 如果查詢語句使用了not in 那么內外表都進行全表掃描,沒有用到索引;而not extsts 的子查詢依然能用到表上的索引。所以無論那個表大,用not exists都比not in要快。 也 就是說,in和exists需要具體情況具體分析,not in和not exists就不用分析了,盡量用 not exists就好了。
典型的連接類型共有3種:
排序 - - 合并連接(Sort Merge Join (SMJ) ) 嵌套循環(Nested Loops (NL) ) 哈希連接(Hash Join)嵌套循環和哈希連接的算法還是有不同,在理論上哈希連接要快過排序和nl,當然實際 情況比理論上有復雜的多,不過兩者還是有差異的.
1 關聯子查詢與非關聯子查詢
關聯子查詢需要在內部引用外部表,而非關聯子查詢不要引用外部表。對于父查詢中處理 的記錄來說,一個關聯子查詢是每行計算一次,然而一個非關聯子查詢只會執行一次,而且結 果集被保存在內存中(如果結果集比較小),或者放在一張oracle臨時數據段中(如果結果集 比較大)。一個“標量”子查詢是一個非關聯子查詢,返回唯一記錄。如果子查詢僅僅返回一個 記錄,那么oracle優化器會將結果縮減為一個常量,而且這個子查詢只會執行一次。select from emp where deptno in (select deptno from dept where dept_name=’admin’);2. 如何選擇?
根據外部查詢,以及子查詢本身所返回的記錄的數目。如果兩種查詢返回的結果是相同的,哪一個效率更好?關聯子查詢的系統開銷:對于返回到外層查詢的記錄來說,子查詢會每次執行一次。因此,必須保證任何可能的時候子查詢都要使用索引。非關聯子查詢的系統開銷:子查詢只會執行一次,而且結果集通常是排好序的,并保存在臨時數據段中,其中每一個記錄在返回時都會被父級查詢引用,在子查詢返回大量記錄的情況下,將這些結果集排序回增大系統的開銷。所以:如果父查詢只返回較少的記錄,那么再次執行子查詢的開銷不會非常大,如果返回很多數據行,那么直查詢就會執行很多次。 如果子查詢返回較少的記錄,那么為內存中保存父查詢的結果集的系統開銷不會非常大,如果子查詢返回多行,那么需要將結果放在臨時段上,然后對數據段排序,以便為負查詢中的每個記錄服務。3.結論
- 在使用一個關聯子查詢是,使用in 或者 exists子句的子查詢執行計劃通常都相同
- exists子句通常不適于子查詢
- 在外部查詢返回相對較少記錄時,關聯子查詢比非關聯子查詢執行得要更快。
- 如果子查詢中只有少量的記錄,則非關聯子查詢會比關聯子查詢執行得更快。
4 子查詢轉化:子查詢可以轉化為標準連接操作
- 使用in的非關聯子查詢(子查詢唯一)條件:1.在整個層次結構中最底層數據表上定義唯一主鍵的數據列存在于子查詢的select列表中2.至少有個定義了唯一主鍵的數據列在select列表中,而且定義唯一主鍵的其他數據列都必須有指定的相等標準,不管是直接指定,還是間接指定。- 使用exists子句的關聯子查詢條件:對于相關條件來說,該子查詢只能返回一個記錄。5. not in和not exists調整
- not in 非關聯子查詢:轉化為in寫法下的minus子句- not exists關聯子查詢:這種類型的反連接操作會為外部查詢中每一個記錄進行內部查詢,除了不滿足子查詢中where條件的內部數據表以外,他會過濾掉所有記錄。可以重寫:在一個等值連接中指定外部鏈接條件,然后添加select distinct ... from a,b where a.col1 = b.col1(+) and b.col1 is null6. 在子查詢中使用all any
原文地址
如果有侵權,馬上刪除
總結
以上是生活随笔為你收集整理的in和exists以及not in 和not exists有什么不同?(笔记)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Codeforces Round #48
- 下一篇: 服务器集群技术(备份服务器方案和均摊工作