多表連接 (Join) 時,優化器需在 N! 種連接順序中尋找最低 Cost 路徑。當表數超過 10,排列組合爆炸 (15 表 > 1 兆種),解析時間可能超過執行時間。本文詳細說明控制優化器搜尋空間的參數與 Hint 實戰技巧。
| 參數 | 預設 | 效果 |
| OPTIMIZER_SEARCH_LIMIT | 5 | 表數 ≤ 此值 → 窮舉所有排列;> 此值 → 改用啟發式/動態規劃搜尋,不保證全域最優。 |
| OPTIMIZER_MAX_PERMUTATIONS | 80,000 | 最大評估排列數上限 (舊版參數,11g+ 內部動態規劃自動控制,建議勿手動調整)。 |
手工指定連接順序:ORDERED & LEADING
ORDERED Hint
SELECT /*+ ORDERED USE_NL(dept) */ e.ename, d.dname
FROM emp e, dept d
WHERE e.deptno = d.deptno;
- 強制依 **FROM 子句順序** 連接,第一張表為驅動表 (Outer)。
- 常搭配
USE_NL, USE_HASH, LEADING 微調。
LEADING Hint (推薦,更靈活)
SELECT /*+ LEADING(e d) USE_HASH(e d) USE_NL(s b) */
...
FROM emp e, dept d, sal s, bonus b
WHERE ...;
- 指定**連接順序清單**,不綁定 FROM 子句順序。
- 可部分指定:
LEADING(e d) 只固定前兩表。
實戰調優流程
- 收集完整統計資訊 (含直方圖)。
- Session 級暫時調大
OPTIMIZER_SEARCH_LIMIT 讓優化器窮舉找最佳順序。
- 觀察執行計畫,提取最佳連接順序。
- 將順序寫入
LEADING Hint,或建立 **SQL Plan Baseline** 固化。
- 恢復參數預設值。
連接順序選擇原則
「先過濾最嚴格的表 (最小結果集) 驅動,後連接大表;驅動表走索引範圍掃描,被驅動表走索引唯一/範圍掃描。」
- 將 **WHERE 條件最強、回傳行數最少** 的表放在最前 (驅動表)。
- 被驅動表的 JOIN KEY **必須有索引** 才能高效 Nested Loops。
- 避免大表做驅動表 (除非有極佳索引過濾)。
監控與驗證
-- 查看實際連接順序
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('sql_id', NULL, 'ALL'));
-- 關鍵欄位:OPERATION (NESTED LOOPS / HASH JOIN), OBJECT_NAME, OPTIONS
- 上一篇文章: 深入解析 Oracle 全域暫存表(Global Temporary Table)機制與應用
- 下一篇文章: Oracle 參數模糊查詢技巧:SHOW PARAMETER 配合通配符快速定位
Copyright ©
程式碼之家 All Rights Reserved