not in和not exists區別


如果查詢語句使用了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結論:

1)在使用一個關聯子查詢是,使用in 或者 exists子句的子查詢執行計划通常都相同 
2)exists子句通常不適於子查詢 
3)在外部查詢返回相對較少記錄時,關聯子查詢比非關聯子查詢執行得要更快。 
4)如果子查詢中只有少量的記錄,則非關聯子查詢會比關聯子查詢執行得更快。

4 子查詢轉化:子查詢可以轉化為標准連接操作

   1)使用in的非關聯子查詢(子查詢唯一)

      條件:1)在整個層次結構中最底層數據表上定義唯一主鍵的數據列存在於子查詢的select列表中

            2)至少有個定義了唯一主鍵的數據列在select列表中,而且定義唯一主鍵的其他數據列都必須有指定的相等標准,不管是直接指定,還是間接指定。

   2)使用exists子句的關聯子查詢

      條件:對於相關條件來說,該子查詢只能返回一個記錄。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

5。not in和not exists調整

1)not in 非關聯子查詢:轉化為in寫法下的minus子句

2)not exists關聯子查詢:這種類型的反連接操作會為外部查詢中每一個記錄進行內部查詢,除了不滿足子查詢中where條件的內部數據表以外,他會過濾掉所有記錄。

可以重寫:在一個等值連接中指定外部鏈接條件,然后添加select distinct

eg:select distinct ... from a,b where a.col1 = b.col1(+) and b.col1 is null


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM