Oracle
謂詞中帶有“或”的慢連接行為
我面臨著我無法理解和克服的情況。
簡而言之,我們有左連接查詢,例如:
select from a left join b on a.key1=b.key1 or a.key1=b.key2
這工作非常緩慢,同時兩者分開:
select from a left join b on a.key1=b.key1 select from a left join b on a.key1=b.key2
工作非常快。
b.key1 具有正常索引
b.key2 具有正常索引
我無法理解這種行為的原因?我是否在加入策略或索引使用中遺漏了一些非常基本的東西?
在這裡,我們有詳細的計劃:
WITHOUT OR(TOP_USTR_ADMIN_IP - ustrip 列的索引名稱):
SQL> explain plan for SELECT * FROM top.macs_constraint mc LEFT JOIN top.top_ustr tu ON tu.ustrip = mc.IP; Explained. SQL> SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY()); Plan hash value: 349751289 -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 22 | 1296 (1)| 00:00:16 | | 1 | SORT AGGREGATE | | 1 | 22 | | | |* 2 | HASH JOIN RIGHT OUTER| | 981K| 20M| 1296 (1)| 00:00:16 | |* 3 | INDEX FAST FULL SCAN| TOP_USTR_ADMIN_IP | 23187 | 181K| 62 (0)| 00:00:01 | | 4 | TABLE ACCESS FULL | MACS_CONSTRAINT | 629K| 8601K| 1231 (1)| 00:00:15 | -------------------------------------------------------------------------------------------- PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("TU"."USTRIP"(+)="MC"."IP") 3 - filter("TU"."USTRIP"(+) IS NOT NULL)
與或:
explain plan for SELECT count(*) FROM top.macs_constraint mc LEFT JOIN top.top_ustr tu ON (tu.ustrip = mc.IP or tu.skladIP = mc.IP); Explained. SQL> SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY()); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------------------------------------------------- Plan hash value: 2704565128 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 14 | 322M (1)|999:59:59 | | 1 | SORT AGGREGATE | | 1 | 14 | | | | 2 | NESTED LOOPS OUTER | | 1887K| 25M| 322M (1)|999:59:59 | | 3 | TABLE ACCESS FULL | MACS_CONSTRAINT | 629K| 8601K| 1231 (1)| 00:00:15 | | 4 | VIEW | | 3 | | 513 (1)| 00:00:07 | |* 5 | TABLE ACCESS FULL| TOP_USTR | 3 | 72 | 513 (1)| 00:00:07 | PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 5 - filter("TU"."SKLADIP" IS NOT NULL AND "TU"."SKLADIP"="MC"."IP" OR "TU"."USTRIP" IS NOT NULL AND "TU"."USTRIP"="MC"."IP")
為什麼
or
在謂詞中使用會給出嵌套循環並且沒有索引使用?是否可以強制使用索引?更新: “沒有或”的錯誤計劃。已修復
OR 速度較慢,因為您不再可以執行索引查找,但有效地強制數據庫引擎查看索引樹中的每個葉節點。使用單個參數(無 OR),引擎可以通過索引向下查找相關葉節點,但是當您向它詢問 OR 時,它會掃描整個葉節點範圍。
如果性能太慢而無法容忍,請按照評論的建議進行操作並嘗試 UNION(無重複值)或 UNION ALL(允許重複值),甚至兩個單獨的查詢,然後在程式碼中將結果連接在一起層接收結果。