索引透過 B*Tree 將邏輯值映射至 ROWID,實現 O(log n) 存取。但索引非越多越好——寫入開銷、空間佔用、優化器誤判風險並存。本文提供索引建立決策框架、大表分區索引策略、聚簇替代方案、表索引物理隔離最佳實踐。
| 條件 | 動作 | 理由 |
|---|---|---|
| 欄位出現在 WHERE/JOIN/ORDER BY/GROUP BY | 候選建立索引 | 存取路徑最短化 |
| 選擇性 < 1-2% (高選擇性) | 強烈建議 B*Tree 索引 | 索引掃描成本遠低於 FTS |
| 選擇性 > 5-10% (低選擇性) | 通常不建立,或考慮位圖索引 (DW) | FTS 多區塊讀取更高效 |
| 欄位頻繁 UPDATE/DELETE | 謹慎建立,評估 DML 開銷 | 索引維護產生 Redo/Undo、分裂/合併 |
| 複合索引導引欄位未在條件中 | 不建立或調整欄位順序 | 無法利用索引範圍掃描 |
| 隱性型別轉換風險 (數字比較字串) | 修正應用/加入函數索引 | 導致索引失效、FTS |
問題:大表索引佔用大量 Buffer Cache (索引塊優先級高),擠佔資料塊,導致頻繁物理讀、效能抖動。
方案:Local Partitioned Index (本地分區索引)
| 類型 | 機制 | 適用場景 | 限制 |
|---|---|---|---|
| 索引聚簇 | 多表按叢集鍵值混合儲存同一區塊,叢集鍵建 B*Tree 索引 | 父子表固定關聯、高頻 JOIN、主鍵-外鍵模式 | 叢集鍵值更新昂貴、不支援分區、全表掃描變慢 |
| 雜湊聚簇 | 按叢集鍵雜湊分桶,無索引,直接定位區塊 | 等值查詢為主、叢集鍵值分布均勻 | 範圍查詢不支援、桶溢出鏈長影響效能 |
| 任務 | 頻率 | 指令/腳本 |
|---|---|---|
| 統計收集 | 每日/變更後 | DBMS_STATS.GATHER_INDEX_STATS (CASCADE=TRUE) |
| 碎片檢測 | 每週 | HEIGHT > 3 / PCT_USED < 50% / DELETED_LEAF_ROWS > 20% |
| 重建/縮減 | 碎片超標時 | ALTER INDEX ... REBUILD ONLINE / COALESCE / SHRINK SPACE |
| 未用索引識別 | 每月 | V$OBJECT_USAGE (ALTER INDEX ... MONITORING USAGE) |
| 反向鍵索引 | 熱點右側插入 | CREATE INDEX ... REVERSE (序列/時間鍵) |
| 類型 | 適用場景 | 關鍵語法 |
|---|---|---|
| 函數索引 | WHERE UPPER(name) = 'SMITH' | CREATE INDEX idx_upper_name ON emp(UPPER(ename)) |
| 位圖索引 | DW 低基數欄位、多條件 AND/OR | CREATE BITMAP INDEX idx_sex ON emp(sex) |
| 反向鍵索引 | 序列/時間主鍵右側熱點 | CREATE INDEX idx_rev ON t(seq_col) REVERSE |
| 不可見索引 | 測試索引效果不影響生產 | CREATE INDEX ... INVISIBLE / ALTER INDEX ... INVISIBLE |
| 部分索引 (12c+) | 僅索引滿足條件的列 | CREATE INDEX ... WHERE status = 'ACTIVE' |
索引是把雙刃劍:精準建立、分區對齊、物理隔離、持續監控、按需進階,才能在讀寫平衡點上持續獲取淨收益。