三表 A, B, C 已收集統計資訊。原始查詢:
SELECT A.col4 FROM C, A, B
WHERE C.col3 = 5 AND A.col1 = B.col1 AND A.col2 = C.col2 AND B.col3 = 10;
初始計畫:HASH JOIN → MERGE JOIN CARTESIAN (B × C) → FULL SCAN A,笛卡爾積風險極大。
| Hint | 計畫關鍵變化 | Cost |
|---|---|---|
/*+ ORDERED */ | FROM 子句順序 C→A→B,雜湊連接 C-A 再雜湊 B | 5 |
/*+ ORDERED USE_NL(A C) */ | C 驅動 A 嵌套循環,再雜湊 B | 7 |
/*+ USE_NL(A C) */ (無 ORDERED) | 同前,優化器自行決定驅動順序 | 7 |
/*+ ORDERED USE_NL(A B C) */ | 全嵌套循環 C→A→B,Cost 飆升至 35 | 35 |
心得: USE_NL / USE_HASH **必須搭配 ORDERED** 才能精確控制驅動表,否則優化器可能忽略或重排。
swd_billdetail (B) 5,392 萬行,PK id,索引 idx_detail_cn (cn 非唯一,大量重複)。super_user (A) 2,800 行,索引 idx_super_user_cn。SELECT COUNT(A.channel || B.user_class)
FROM swd_billdetail B, super_user A
WHERE A.cn = B.cn;
SELECT /*+ ORDERED USE_NL(A) */ COUNT(A.channel || B.user_class)
FROM swd_billdetail B, super_user A
WHERE A.cn = B.cn;
cn 唯一,方案 1 可能更好;若 super_user 也有 500 萬行,方案 2 會變差。**具體問題具體分析,無統一標準。**無論 OPTIMIZER_MODE 如何設定,滿足下列任一條件**強制 CBO**:
PARALLEL DEGREE > 1 (7.3+)。RULE、ALL_ROWS、FIRST_ROWS 之外的 Hint。優先級由高到低:Non-RBO Object → Parallelism → RULE Hint → ALL_ROWS Hint → FIRST_ROWS Hint → Other Hint → OPTIMIZER_GOAL=RULE/ALL_ROWS/FIRST_ROWS/CHOOSE (CHOOSE 視物件是否分析決定 RULE/ALL_ROWS)。PL/SQL 內部固定 ALL_ROWS。
/*+ RULE */ 對比。綁定變數雙刃劍: 減少 Hard Parse 但隱藏列統計 (直方圖) 導致計畫固化偏差。11g+ Adaptive Cursor Sharing 部分緩解。