1. 程式人生 > >16 反連線(anti-join)--優化主題系列

16 反連線(anti-join)--優化主題系列

反連線(anti-join)

反連線其實是特殊的半連線。只是把in/exists換成了notin/not exists

執行計劃中,看到有NESTED LOOPS ANTI/HASH JOIN ANTI 就表示有反連線

舉個例子(基於HROracle11gR2)下面有2SQL

select department_name

 from hr.departments dept

 where department_id NOT IN

 (select department_id from hr.employees emp);

select department_name

 from hr.departments dept

 where NOT EXISTS (select null from hr.employees emp

 where emp.department_id = dept.department_id);

以上兩個SQL不等價


NOT IN執行計劃是filter對吧??


NOT EXISTS就是正常的JOIN方式了吧

令人驚訝的是,not in不返回結果,notexists返回16行。

這裡也說明not innotexists不能像inexists那樣隨意改寫SQL

為什麼用not in不返回結果呢??因為子查詢

select department_id from hr.employees emp

會返回NULL值。Oracle有個缺陷:

in裡面有NULL會返回結果,比如下面SQL

select department_name from hr.departments dept wheredepartment_id in(10,50,null);

not in 裡面有NULL就不會返回結果,直接返回NULL

select department_name from hr.departments dept wheredepartment_id not in(10,50,null);

我們在做SQL優化的時候,一定要注意not innotexists是不是能等價轉換。

當然了,一般情況下,

notin子查詢裡面都會排除有NULL的情況,不然查詢結果沒意義。

現在來過濾掉NULL值。


A LEFT JOIN B 是不是說A並且B沒有 BNULL代替

那我加個where條件 IS NULL

B.XXX IS NULL 是不是說明AB 沒關聯上??

是不是等效於 NOTIN,NOT EXISTS的效果

總結一下in/existsnotin/not exists 一般情況下,當SQL很簡單,他們的執行計劃是一樣的,也就是說他們的效能時一樣的。但是SQL一複雜了,他們的執行計劃就可能不一樣,這個時候就要我們去解決這些問題。這裡,我不會給你們講什麼情況下應該用notin什麼情況下應該用notexists,因為這些理論是沒用的,要具體情況具體分析。後面的章節我會講解半連線和反連線最底層的原理,把最底層原理搞懂之後,大家以後在遇到inexistsnot innotexists就會迎刃而解了。