對this answer的評論指出,反連接可能已經過優化,以便在Oracle中進行外連接更高效。我有興趣看看有什麼解釋/證據可以支持或否定這一說法。反連接是否比左外連接更高效?
3
A
回答
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連接在某些情況下也可能比內部連接+明顯好得多。
相關問題
- 1. 左連接 - 如何更高效?
- 2. 哪個更好..左外連接還是右外連接?
- 3. 連接整數列比連接PostgreSQL中的varchar更高效?
- 4. 更新左外連接表
- 5. SQL:左連接左連接結果左連接左連接/右連接
- 6. 左外連接IEnumerable
- 7. 左外連接 - SQL2005
- 8. Linq左外連接
- 9. 左外連接SOQL
- 10. 左連接與全外連接組合
- 11. SQL左外連接與n:m連接表
- 12. 內有多個左外連接連接
- 13. 這是左連接還是右連接,內部還是外部?
- 14. 左連接更新?
- 15. 更改左連接到基本連接
- 16. 如何在XQuery中進行高效的外部或左連接?
- 17. 交叉連接,然後是左連接
- 18. LINQ - 左外連接 - 更好的方法
- 19. 左外連接返回更少的行
- 20. 以下linq執行左外連接而不是內連接
- 21. NHibernate的左外連接
- 22. 左外部連接問題
- 23. 約左外連接SQL
- 24. 兩個左外連接
- 25. Oracle SQL左外部連接
- 26. 左外連接問題
- 27. 真正的左外連接
- 28. 左外連接中的LINQ
- 29. Linq左外部連接C#
- 30. Subsonic3 LINQ左外連接
在執行計劃和效率方面,我發現喬納森劉易斯的文章總是值得一讀。 (Jonathan是OTN的常規撰稿人 - Oracle針對SQL和PL/SQL的討論論壇,也是Oracle優化方面最博學的人士之一。)下面是一個例子 - 一篇文章,其中的問題不是空白的「加入vs定期加入過濾器「,但在我看來,討論足夠的東西是爲了讓每個人都瞭解發生的事情。 https://jonathanlewis.wordpress.com/2015/04/13/not-exists/ – mathguy
感謝Jonathan Lewis的參考。他的東西總是做得很好。 –