首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

為什麼 Oracle 有時不使用索引?優化器決策邏輯與六大排查步驟全解析

     編輯:Oracle 資料庫基礎

SQL 執行計劃生成九步曲

  1. 語法分析
  2. 語義分析
  3. 視圖轉換
  4. 表達式轉換
  5. 選擇優化器
  6. 選擇連接方式
  7. 選擇連接順序
  8. 選擇資料搜尋路徑(全表掃描 vs 索引)
  9. 執行計劃執行

兩代優化器:RBO vs CBO

優化器模式參數


SHOW PARAMETER optimizer_mode;
-- 預設 CHOOSE:有統計資訊用 CBO,無則用 RBO
-- 可設 RULE、FIRST_ROWS、ALL_ROWS 等

索引未被使用的六大排查步驟

1. 確認優化器模式

  • 若 OPTIMIZER_MODE = RULE,CBO 相關功能全關閉
  • 建議設 ALL_ROWS(全表最優)或 FIRST_ROWS_n(響應優先)

2. 檢查 WHERE 條件是否包含索引前導欄

  • 複合索引 (A,B,C),查詢必須包含 A 才可能用到索引
  • WHERE B = 1 → 索引無效(除非 Index Skip Scan)

3. 連接方式是否支援索引利用

特性RBO (Rule-Based)CBO (Cost-Based)
引入版本Oracle 6Oracle 7
決策依據固定規則排名統計資訊計算 Cost
對資料敏感度不敏感高度敏感
新功能支援無星型連接、雜湊連接、平行查詢
現狀已停止發展主流、持續增強

若 Optimizer 選擇 Hash Join,內表索引再好也用不上。

4. 連接順序是否允許索引生效

  • 外表(Driving Table)永遠**全表掃描**
  • 若大表在外、小表在內且有索引 → 索引浪費
  • 對策:/*+ ORDERED */ 或 /*+ LEADING(t_small) */ 強制小表驅動

5. 是否涉及資料字典表/視圖

  • 字典表無統計資訊 → CBO 產生極差計劃
  • **嚴禁自行分析字典表**,恐導致死鎖/效能崩壞
  • 對策:改寫查詢避免直接查字典,或用 Hint 強制 RBO

6. 隱性資料型態轉換

  • WHERE char_col = 123 → Oracle 隱性 TO_NUMBER(char_col) → 索引失效
  • WHERE num_col = '123' → 隱性 TO_CHAR(num_col) → 索引失效
  • 對策:應用層嚴格型別綁定,SQL 明確轉換 TO_CHAR/TO_NUMBER/TO_DATE

進階診斷工具


-- 1. 觀察實際執行計劃
EXPLAIN PLAN FOR SELECT ...;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

-- 2. 10053 追蹤(CBO 決策內幕)
ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';
-- 執行 SQL 後查看 trace 檔

-- 3. 統計資訊健康度
SELECT table_name, last_analyzed, num_rows, blocks
FROM user_tables
WHERE last_analyzed < SYSDATE - 30;  -- 超過 30 天未分析

最佳實務總結

  1. **統計資訊是 CBO 生命線**:定期 DBMS_STATS.GATHER_TABLE_STATS,採樣 10-20%
  2. **索引設計遵循「選擇性高、前導欄在 WHERE」原則**
  3. **避免隱性轉換**:應用程式使用繫結變數正確型別
  4. **複雜查詢用 Hint 微調而非硬編碼**
  5. **定期收集系統統計**:DBMS_STATS.GATHER_SYSTEM_STATS 讓 CBO 瞭解硬體特性

索引不被使用通常不是 Bug,而是優化器基於成本模型的理性選擇。掌握上述六大排查步驟,您就能像優化器一樣思考,精準診斷、有效干預。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
連接方法能否有效利用內表索引
Nested Loops是**
Sort Merge Join僅能避免排序,無法加速存取
Hash Join幾乎無影響(需建雜湊表)