SQL 調優千頭萬緒,但 **90% 的收益來自 2 個核心決策**:**選對優化器模式**、**選對表存取路徑**。本文直擊本質,拒絕碎片化技巧,建立系統性調優決策框架。
Oracle 提供三種優化器模式 (10g 後 RULE 已棄用,但理解歷史有助於遷移):**RBO (Rule-Based)、CBO (Cost-Based)、CHOOSE (相容模式)**。
| 模式 | 決策依據 | 適用場景 | 設定方式 |
|---|---|---|---|
| RBO | 固定規則矩陣 (索引存在即用、全表掃描最後手段) | 極舊版本、極簡單查詢、統計資訊極難維護的 Legacy | `OPTIMIZER_MODE=RULE` / `/*+ RULE */` |
| CBO | **統計資訊 + 成本模型** 估算 CPU/IO/Network 成本,選最低成本計畫 | **所有現代生產環境 (10g+ 預設)** | `OPTIMIZER_MODE=ALL_ROWS` / `FIRST_ROWS_n` / `/*+ ALL_ROWS */` |
| CHOOSE | 有統計資訊 → CBO;無統計資訊 → RBO | **相容模式,新系統禁用** | `OPTIMIZER_MODE=CHOOSE` (預設 9i-) |
-- 必須定期收集 (含直方圖)
EXEC DBMS_STATS.GATHER_TABLE_STATS(
ownname => 'SCOTT',
tabname => 'EMP',
estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
method_opt => 'FOR ALL COLUMNS SIZE AUTO', -- 自動直方圖
cascade => TRUE, -- 同步索引統計
degree => 8 -- 平行收集
);
-- 系統級自動收集 (10g+ 預設啟用)
-- 維護窗口: WEEKNIGHT_WINDOW, WEEKEND_WINDOW
-- 查詢自動任務狀態
SELECT client_name, status, window_name FROM dba_autotask_client;
鐵律:**CBO 無統計資訊 = 瞎子摸象**。新表、大量變更表、分區表、斜欄位**必須**手動/排程收集統計資訊。
ALL_ROWS (預設):**最小化總資源消耗**,適合批次、報表、資料倉庫、API 後端。FIRST_ROWS_1/10/100/1000:**最小化首筆/前 N 筆回應時間**,適合互動式查詢、分頁首頁、即時搜尋。會傾向 Nested Loop + Index Access Path。Oracle 存取表中資料,**只有兩種物理路徑**:
| 因子 | 有利 Index | 有利 FTS |
|---|---|---|
| 選擇率 (Selectivity) | < 1-5% | > 5-10% |
| 聚簇因子 | 接近 Blocks (資料依索引序排列) | 接近 Rows (資料隨機分布,回表跳躍大) |
| 索引欄位 | WHERE/JOIN/ORDER BY 使用前導欄位 | 函數運算、隱式轉換、不等式 (!=, <>) 導致索引失效 |
| 並行度 | 串行 | PARALLEL (FTS 並行效率極高) |
SQL 進入 │ ├─ 是否有統計資訊? → 無 → 收集統計資訊 (DBMS_STATS) → 重試 │ ├─ 優化器模式? → CHOOSE/RULE → 改 ALL_ROWS 或 FIRST_ROWS_n │ ├─ 執行計畫 → 看存取路徑 │ ├─ FTS → 選擇率高/聚簇因子差/無索引/並行 → **合理** → 結束 │ │ → 不合理 → 檢查統計資訊/直方圖/索引定義/Hint │ │ │ └─ Index Access → 選擇率低/聚簇因子好 → **合理** → 結束 │ → 不合理 → 強制 FTS (FULL Hint) / 重建索引 / 改寫 SQL │ └─ 效能達標? → 否 → 進階調優 (Join 方法/順序、子查詢轉換、分區剪枝、並行、Hint、SQL Profile、Baseline)
掌握這兩步,您已超越 80% 的「索引迷信者」與「Hint 依賴者」。後續進階 (Join、子查詢、分區、並行、Baseline) 皆建立在此基石之上。