執行計劃核心欄位解讀
優化器模式判斷
SELECT STATEMENT Optimizer=CHOOSE (Cost=1234 Card=1 Bytes=14)
TABLE ACCESS FULL LARGE_TABLE [:Q65001] [ANALYZED]
- Optimizer=CHOOSE:初始化參數值,非實際使用優化器
- Cost=數值:CBO 模式(有成本計算)
- Cost=空值或無 Cost:RBO 模式
- [:Qxxxxx]:平行查詢 Slave 進程
- [ANALYZED]:物件有統計資訊,CBO 可用
優化器模式對照表
| Optimizer 值 | 實際優化器 |
| ALL_ROWS / FIRST_ROWS / FIRST_ROWS_n | CBO |
| RULE | RBO |
| CHOOSE + Cost=數值 | CBO |
| CHOOSE + Cost=空 | RBO |
多表連接執行計劃深度分析
測試場景
- 表 A、B、C 均為大表
- A 有複合索引
INX_COL12A (col1, col2),col1 為引導欄
- 查詢:
WHERE B.col3=10 AND A.col1=B.col1 AND A.col2=C.col2 AND C.col3=5
執行計劃結構
SELECT STATEMENT Optimizer=CHOOSE
0 MERGE JOIN
1 SORT (JOIN)
2 NESTED LOOPS
3 TABLE ACCESS (FULL) OF 'B'
3 TABLE ACCESS (BY INDEX ROWID) OF 'A'
5 INDEX (RANGE SCAN) OF 'INX_COL12A' (NON-UNIQUE)
1 SORT (JOIN)
7 TABLE ACCESS (FULL) OF 'C'
連接順序推導邏輯
- 移除索引掃描行(輔助操作,非主要存取)
- 最右、最上優先:縮進最多、位置最上者最先執行
- 結果:
TABLE ACCESS FULL B → 驅動表(外部表)
- 連接順序:B → A → C
為何 B 為最佳驅動表?
- B 有過濾條件
col3=10,全表掃描後產生小結果集
- 連接條件
A.col1=B.col1 可用 A 索引引導欄
- 若 C 為驅動表:
A.col2=C.col2 無法用索引(col2 非引導欄),NL 效能差
優化器干預:HINT 強制連接順序
SELECT /*+ ORDERED */ A.col4
FROM B, A, C
WHERE B.col3 = 10
AND A.col1 = B.col1
AND A.col2 = C.col2
AND C.col3 = 5;
ORDERED 指示 CBO 依 FROM 子句順序連接,配合將驅動表寫在最前。
RBO 模式驗證實驗
實驗結論
- 文檔稱「FROM 右到左選擇驅動表」未驗證成功
- 實測:RBO 仍考慮索引存在性與 WHERE 條件,非單純順序決定
- 刪除索引後:RBO 轉為 MERGE JOIN 全表掃描
- RBO 無法用 HINT 強制 NL(會隱性切換 CBO)
驅動表選擇黃金法則
| 原則 | 說明 |
| 有過濾條件的表優先 | WHERE 子句可大幅縮減結果集 |
| 連接欄位有索引引導欄 | 支援高效 NESTED LOOPS |
| 小結果集驅動大表 | 減少內部表存取次數 |
| 統計資訊必須準確 | CBO 依賴統計資訊決策 |
執行計劃閱讀檢查清單
- 識別優化器模式(CBO/RBO)
- 移除索引掃描輔助行
- 按「最右最上」找首個表存取 → 驅動表
- 追蹤連接順序與連接方式(NL/MSJ/HJ)
- 檢查索引使用情況(RANGE SCAN vs FULL SCAN)
- 評估驅動表選擇是否最優,否則加 HINT 或重寫 SQL