| 維度 | B-Tree 索引 | Bitmap 索引 |
|---|---|---|
| 存儲結構 | 平衡樹,存儲 (Key, RowID) | 位圖矩陣,每個唯一值對應一個位圖 |
| 適用基數 | 高基數(唯一值多) | 低基數(唯一值少,如性別、狀態) |
| 並發 DML | 行級鎖,高並發友好 | 位圖段鎖,嚴重鎖衝突 |
| 空值處理 | 不索引全 NULL 行 | 索引 NULL 值 |
| 查詢優勢 | 精確查找、範圍掃描 | 多條件 AND/OR/XOR 組合、計數統計 |
| 典型場景 | OLTP 核心業務表 | 數據倉庫、DSS、星型模型 |
測試表:TEST_NORMAL(100萬行),GENDER(M/F),SAL(9個離散值)
查詢:SELECT * FROM test_normal WHERE sal IN (1000,1500,...,5000) AND gender='M'
| Id | Operation | Name |
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID | TEST_NORMAL |
| 2 | BITMAP CONVERSION TO ROWIDS | |
| 3 | BITMAP INDEX SINGLE VALUE | NORMAL_GENDER_BMX |
統計:Consistent Gets = 6,280
| Id | Operation | Name |
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID | TEST_NORMAL |
| 2 | INDEX RANGE SCAN | NORMAL_GENDER_IDX |
統計:Consistent Gets = 6,854
Bitmap 索引通過位圖合並操作,將多條件轉化為位運算,邏輯讀降低 8.4%。隨著條件增加,優勢愈發明顯。
是否為 OLTP 系統(高並發增刪改)?
├─ 是 → 必選 B-Tree 索引
└─ 否(DSS/數倉/報表系統)
├── 基數極低(< 50 個唯一值)? → Bitmap 索引
├── 需頻繁多列組合過濾(>5 列)? → Bitmap 索引(突破 AND_EQUAL 5列限制)
├── 需統計 NULL 值? → Bitmap 索引
├── Ad-hoc 查詢模式不可預測? → Bitmap 索引
└── 其他 → B-Tree 索引
優化器可將多個 Bitmap 索引通過 BITMAP AND/OR/XOR 合並,生成最終 RowID 集合,無需訪問表即可完成過濾。
-- 事實表建立多個 Bitmap 索引
CREATE BITMAP INDEX fact_time_bmx ON sales_fact(time_key);
CREATE BITMAP INDEX fact_prod_bmx ON sales_fact(prod_key);
CREATE BITMAP INDEX fact_cust_bmx ON sales_fact(cust_key);
CREATE BITMAP INDEX fact_chan_bmx ON sales_fact(channel_key);
-- 任意維度組合查詢自動使用 Bitmap 合並
SELECT SUM(amount) FROM sales_fact f
JOIN time_dim t ON f.time_key = t.time_key
JOIN prod_dim p ON f.prod_key = p.prod_key
WHERE t.year = 2023 AND p.category = 'Electronics';
Bitmap 索引包含 NULL 值,SELECT COUNT(*) FROM table 可直接掃描最小 Bitmap 索引,無需全表掃描。
WHERE created_date > SYSDATE - 30-- 核心交易表:B-Tree 為主
CREATE UNIQUE INDEX pk_orders ON orders(order_id);
CREATE INDEX idx_orders_cust ON orders(customer_id); -- FK
CREATE INDEX idx_orders_date ON orders(order_date); -- 範圍查詢
-- 維度/屬性列:Bitmap 輔助
CREATE BITMAP INDEX bmx_orders_status ON orders(status); -- 低基數
CREATE BITMAP INDEX bmx_orders_channel ON orders(channel); -- 低基數
CREATE BITMAP INDEX bmx_orders_pay_type ON orders(pay_type); -- 低基數
| 操作 | B-Tree 開銷 | Bitmap 開銷 | 建議 |
|---|---|---|---|
| INSERT | O(log N) | 鎖定整個位圖段,可能阻塞併發 | 批量載入用 /*+ APPEND */ 直路徑插入 |
| UPDATE 索引列 | 刪除舊條目+插入新條目 | 同 INSERT,且位圖段可能分裂 | 避免更新 Bitmap 索引列 |
| DELETE | 標記刪除 | 位圖置 0,空間不自動回收 | 定期 ALTER INDEX ... REBUILD |
| 統計信息收集 | 快速 | 需計算基數、聚簇因子 | DBMS_STATS.GATHER_TABLE_STATS METHOD_OPT=>'FOR ALL INDEXED COLUMNS' |