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

Oracle 索引不被使用的 12 大原因與排查實戰:從優化器原理到 Hint 強制與追蹤診斷

     編輯:Oracle 資料庫基礎

SQL 執行九步曲與優化器決策點

  1. 語法分析
  2. 語義分析 (物件存在性、權限)
  3. 視圖轉換
  4. 表達式轉換
  5. 選擇優化器 (RBO/CBO) —— 關鍵分水嶺
  6. 選擇連接方式 (NL/SMJ/HJ)
  7. 選擇連接順序
  8. 選擇資料存取路徑 (全表掃描 vs 索引) —— 核心決策
  9. 執行計劃執行

兩代優化器:RBO vs CBO

現代鐵律:生產環境必須用 CBO,並定期收集統計資訊 (DBMS_STATS.GATHER_TABLE_STATS),設定 OPTIMIZER_MODE=ALL_ROWS 或 FIRST_ROWS_n。

索引失效 12 大經典原因排查清單

特性RBO (Rule-Based)CBO (Cost-Based)
決策依據固定規則排名 (索引 > 全表)統計資訊計算 Cost,取最低
對資料敏感度不敏感高度敏感
新特性支援無 (已停止開發)完整支援 (並行、星型、雜湊連接等)
預設模式 (7.0+)CHOOSE:有統計用 CBO,無統計用 RBO
#原因檢查方法對策
1優化器模式非 CBOSHOW PARAMETER optimizer_mode設 ALL_ROWS,收集統計資訊
2索引欄位未出現在 WHERE檢查 SQL 文本重寫 SQL 或建立覆蓋索引
3連接方式非 Nested Loop執行計劃看 HJ/SMJ用 USE_NL Hint 或調整驅動表
4連接順序導致外表全掃執行計劃連接順序ORDERED Hint 指定小表為驅動
5涉及字典表/視圖無統計計劃出現 SYS 物件避免查字典;禁自行分析字典
6索引欄位被函數包裹WHERE TO_CHAR(dt)='2024'建函數索引或改寫 dt >= ... AND dt < ...
7隱性型別轉換WHERE char_col = 123 → 隱性 TO_NUMBER顯式轉換 WHERE char_col = '123'
8統計資訊過時/缺失LAST_ANALYZED 過久定期 GATHER_TABLE_STATS + 直方圖
9索引選擇性過低 (如性別、狀態)DISTINCT_KEYS / NUM_ROWS < 1%建位圖索引 / 組合索引 / 分區裁剪
10索引欄位含 NULL 需回傳COUNT(*)、WHERE col IS NULL索引不存全 NULL;用 COUNT(1) 或函數索引
11並行查詢 (PQO) 強制全掃計劃有 PX SEND/RECEIVE調整 PARALLEL_DEGREE_POLICY 或 Hint
12Bind 變量窺探導致計劃固化WHERE col > :b1 首次執行值影響OPTIMIZER_ADAPTIVE_CURSOR_SHARING / BIND_AWARE Hint

兩大追蹤診斷利器

1. EXPLAIN PLAN + AUTOTRACE (單句分析)

-- 建立 PLAN_TABLE (一次)
@$ORACLE_HOME/rdbms/admin/utlxplan.sql

SET AUTOTRACE ON
SELECT ...;  -- 顯示計劃、Cost、邏輯讀、物理讀、Bytes 等

2. TKPROF (全程會話級追蹤)

-- 1. 找目標 Session 的 SID, SERIAL#
SELECT sid, serial# FROM v$session WHERE username='APP_USER';

-- 2. 開啟追蹤 (需 DBA 權限)
EXEC DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(sid, serial#, TRUE);

-- 3. 執行業務流程...

-- 4. 關閉追蹤
EXEC DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(sid, serial#, FALSE);

-- 5. 格式化輸出
tkprof /path/to/ora_12345.trc output.txt EXPLAIN=user/pass SYS=NO

輸出檔包含每條 SQL 的執行計劃、CPU、Elapsed、邏輯/物理讀、Rows、庫存等完整指標,快速定位 Top SQL。

Hint 強制使用索引 (最後手段)

SELECT /*+ INDEX(t idx_col1) */ * FROM t WHERE col1 = :val;

規則:/*+ 緊跟 SELECT,+ 無空格,Hint 內部可空格分隔。

總結:系統化排查流程

  1. 確認 CBO 模式 + 統計資訊新鮮度
  2. 檢查 WHERE 條件覆蓋索引前導欄
  3. 觀察連接方式/順序是否阻礙索引
  4. 排除函數/隱性轉換/NULL/並行干擾
  5. 必要時收集直方圖提升選擇性估算
  6. 用 TKPROF 定位會話級 Top SQL 再精準優化
  7. Hint 僅作臨時繞過,根治靠統計與 SQL 改寫
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved