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

Oracle 索引類型選型指南:B-Tree、Bitmap、Function-Based、Composite 實戰決策

     編輯:Oracle 資料庫基礎

索引是查詢效能的倍增器,但「索引越多越好」是危險迷思。本文基於基數、查詢模式、DML 頻率、空間成本四大維度,建立系統化索引選型框架,涵蓋 B-Tree、Bitmap、Function-Based、Composite、Invisible、Partial 等進階類型應用場景。

核心選型決策矩陣

索引類型適用基數典型查詢模式DML 影響空間開銷核心限制
B-Tree (標準)高 (接近唯一)=, >, <, BETWEEN, LIKE 'prefix%'中基準低基數列效能差,NULL 不索引
Bitmap極低 (< 100 不同值)多條件 AND/OR 組合、星狀查詢**極大** (鎖定整個 Bitmap 區塊)極小 (壓縮)**嚴禁 OLTP 高併發 DML**,僅限 DW/批次載入
Function-Based (FBI)視函數結果分布WHERE UPPER(name)='ABC', WHERE TRUNC(dt)=:d同 B-Tree同 B-Tree需收集表統計 + 隱藏虛擬欄統計
Composite (複合)視前導欄基數多欄位組合過濾、排序、分組中較單欄大前導欄原則:最常用於等值過濾、基數最高者在前
Invisible (11g+)同底層類型測試索引移除影響、軟性下線維護成本同在同在優化器忽略,除非設定 OPTIMIZER_USE_INVISIBLE_INDEXES=TRUE
Partial (12c+)同底層類型分區表部分分區索引降低維護範圍節省空間僅支援 Local 分區索引,查詢跨分區需注意

四大選型鐵律

鐵律一:低基數列 + 複合布林邏輯 → Bitmap Index

  • 性別 (M/F)、狀態碼 (0-9)、地區代碼、旗標欄位。
  • WHERE 子句頻見 status='A' AND region='N' OR type='X'。
  • 嚴禁 於高併發 OLTP 表 (大量 INSERT/UPDATE/DELETE) → 嚴重鎖爭用、死鎖溫床。
  • DW 環境:載入完成後建立,查詢前啟用,載入前禁用/刪除。

鐵律二:NULL 值查詢需求 → Bitmap 或 FBI (NVL/DECODE)

B-Tree **不儲存全 NULL 列**。查詢 WHERE id_card IS NULL 會全表掃描。

  • 方案 A:CREATE BITMAP INDEX idx_null ON emp(id_card); (DW 適用)。
  • 方案 B:CREATE INDEX idx_fbi_null ON emp(NVL(id_card,'NULL')); (OLTP 適用),查詢改 WHERE NVL(id_card,'NULL')='NULL'。

鐵律三:小表/低頻查詢表 → 不建索引

  • 行數 < 1,000 或區塊數 < 50:全表掃描極快,索引維護成本 > 查詢收益。
  • 參數表、代碼表、配置表、日誌表 (僅寫入、極少查詢) → **零索引**。
  • 大表但僅報表查詢 (月跑一次) → 僅建 PK/FK 索引,其餘視報表需求臨時建立/刪除。

鐵律四:DML 密集表 → 極度克制索引數量

每個索引 = 每次 DML 額外的「寫入放大」。

  • 高頻交易核心表 (訂單、帳戶流水):**索引數 ≤ 3-4 個** (PK + 1-2 個高選擇率查詢索引 + 必要 FK)。
  • 批次載入表:載入前 **DISABLE/UNUSABLE 非 PK 索引**,載入後 **REBUILD**。
  • 使用 Invisible Index 驗證移除影響:ALTER INDEX idx INVISIBLE; 觀察一週無計畫變化再 DROP。

進階應用模式

Function-Based Index (FBI) 實戰

-- 大小寫不敏感查詢
CREATE INDEX idx_emp_name_upper ON emp(UPPER(ename));
-- 查詢: WHERE UPPER(ename) = 'SMITH'

-- 日期截取 (避免 TRUNC(dt) 導致索引失效)
CREATE INDEX idx_order_dt_trunc ON orders(TRUNC(order_dt));
-- 查詢: WHERE TRUNC(order_dt) = DATE '2024-01-15'

-- JSON/XML 虛擬欄索引 (12c+)
ALTER TABLE orders ADD (order_total_vc NUMBER GENERATED ALWAYS AS (JSON_VALUE(data, '$.total' RETURNING NUMBER)));
CREATE INDEX idx_order_total ON orders(order_total_vc);

關鍵:FBI 建立後 **必須收集統計資訊** (含隱藏虛擬欄),否則優化器無法正確評估基數。

Composite Index 設計黃金法則

  1. 等值優先:WHERE 子句中 = / IN 條件欄位置前。
  2. 基數遞減:同等重要時,基數高 (選擇率低) 者在前。
  3. 排序/分組覆蓋:ORDER BY / GROUP BY 欄位順序與索引前導欄一致可避免 SORT。
  4. 避免過度寬索引:超過 5-6 欄位維護成本激增,考慮 Index Skip Scan (前導欄基數低) 或分拆多個索引。

索引健檢與清理常規

-- 1. 找出長期未使用索引 (11g+ 需啟用監控)
ALTER INDEX idx_name MONITORING USAGE;
-- 一段時間後
SELECT * FROM v$object_usage WHERE used = 'NO';

-- 2. 重複/包含關係索引
-- idx(a,b) 包含 idx(a) -> 後者可刪除

-- 3. 碎片化嚴重索引 (刪除葉列 > 20%)
ANALYZE INDEX idx VALIDATE STRUCTURE;
SELECT name, del_lf_rows/lf_rows*100 pct_del FROM index_stats WHERE pct_del > 20;

-- 4. 空間浪費索引 (Leaf blocks 遠大於理論值)
SELECT index_name, leaf_blocks, blevel, distinct_keys
FROM user_indexes
WHERE leaf_blocks > distinct_keys * 1.5;  -- 經驗值
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved