2017-09-23 25 views
3

this answer的評論指出,反連接可能已經過優化,以便在Oracle中進行外連接更高效。我有興趣看看有什麼解釋/證據可以支持或否定這一說法。反連接是否比左外連接更高效?

+0

在執行計劃和效率方面,我發現喬納森劉易斯的文章總是值得一讀。 (Jonathan是OTN的常規撰稿人 - Oracle針對SQL和PL/SQL的討論論壇,也是Oracle優化方面最博學的人士之一。)下面是一個例子 - 一篇文章,其中的問題不是空白的「加入vs定期加入過濾器「,但在我看來,討論足夠的東西是爲了讓每個人都瞭解發生的事情。 https://jonathanlewis.wordpress.com/2015/04/13/not-exists/ – mathguy

+0

感謝Jonathan Lewis的參考。他的東西總是做得很好。 –

回答

1

當您在SQL查詢中使用「not exists」或「not in」時,讓Oracle選擇合併反連接或散列反連接訪問路徑。

快速說明

例如,給定聯接介乎表A和B(從A加入關於組Ax = Bx的B)Oracle將取從表A的所有相關數據,並嘗試以相應的行匹配它們在表B中,所以它嚴格依賴於表A謂詞的選擇性。

當使用反連接優化時,Oracle可以選擇具有更高選擇性的表並將它與另一個匹配,這可能會導致代碼更快。

它不能通過常規聯接或子查詢來實現,因爲它不能假定表A和B之間的一個匹配足以返回該行。

相關提示: HASH_AJ,MERGE_AJ。

更多:

This貌似關於這個問題一個很好的和詳細的文章。

Here是另一個,更dencet文章。

0

如果Oracle可以將left join + where變爲ANTI join,那麼它完全一樣。

create table ttt1 as select mod(rownum,10) id from dual connect by level <= 50000; 
insert into ttt1 select 10 from dual; 
create table ttt2 as select mod(rownum,10) id from dual connect by level <= 50000; 

select ttt1.id 
    from ttt1 
    left join ttt2 
    on ttt1.id = ttt2.id 
where ttt2.id is null; 

select * from ttt1 where id not in (select id from ttt2); 

如果你看看

Final query after transformations:******* UNPARSED QUERY IS ******* 

在跟蹤事件10053,然後你會看到兩個一模一樣的查詢(你可以看到「=」在跟蹤文件斷言,因爲有在防無特殊符號連接)

SELECT "TTT1"."ID" "ID" FROM "TTT2" "TTT2","TTT1" "TTT1" WHERE "TTT1"."ID"="TTT2"."ID" 

而且他們有完全相同的計劃

----------------------------------- 
| Id | Operation   | Name | 
----------------------------------- 
| 0 | SELECT STATEMENT |  | 
| 1 | HASH JOIN ANTI |  | 
| 2 | TABLE ACCESS FULL| TTT1 | 
| 3 | TABLE ACCESS FULL| TTT2 | 
----------------------------------- 

如果,但是,把一個提示禁用轉換則計劃將

select --+ no_query_transformation 
     ttt1.id 
    from ttt1, ttt2 
where ttt1.id = ttt2.id(+) and ttt2.id is null; 

------------------------------------ 
| Id | Operation   | Name | 
------------------------------------ 
| 0 | SELECT STATEMENT |  | 
| 1 | FILTER    |  | 
| 2 | HASH JOIN OUTER |  | 
| 3 | TABLE ACCESS FULL| TTT1 | 
| 4 | TABLE ACCESS FULL| TTT2 | 
------------------------------------ 

和性能將顯著下降。

如果您將使用帶有deisabled轉換的ANSI連接語法,它將會變得更糟。

select --+ no_query_transformation 
     ttt1.id 
    from ttt1 
    left join ttt2 
    on ttt1.id = ttt2.id 
where ttt2.id is null; 
select * from table(dbms_xplan.display_cursor(format => 'BASIC')); 

-------------------------------------------------- 
| Id | Operation    | Name   | 
-------------------------------------------------- 
| 0 | SELECT STATEMENT  |     | 
| 1 | VIEW     |     | 
| 2 | FILTER    |     | 
| 3 | MERGE JOIN OUTER |     | 
| 4 |  TABLE ACCESS FULL | TTT1   | 
| 5 |  BUFFER SORT  |     | 
| 6 |  VIEW    | VW_LAT_2131DCCF | 
| 7 |  TABLE ACCESS FULL| TTT2   | 
-------------------------------------------------- 

因此,概括地說,如果甲骨文可以申請轉變爲ANTI加入則性能是完全一樣的,否則它可能會更糟。您還可以使用提示「 - + rule」禁用CBO轉換並查看發生了什麼情況。

PS。另外,在某些情況下,即使啓用CBO轉換,SEMI連接在某些情況下也可能比內部連接+明顯好得多。