傳統 B-Tree 聯合索引 (A, B),查詢必須包含前導欄位 A 才能使用索引。若僅查 WHERE B = ?,優化器只能選全表掃描。Oracle 9i 引入 Index Skip Scan(索引跳躍式掃描),打破此限制,特別適合低基數前導欄位 + 高基數後續欄位的聯合索引場景。
假設索引 CREATE INDEX sex_emp_id ON emp(sex, emp_id),sex 只有 'M'/'F' 兩值。查詢 SELECT emp_id FROM emp WHERE emp_id = 123 不指定 sex。
Oracle 內部將其轉換為多個子查詢的 UNION ALL:
SELECT emp_id FROM emp WHERE sex = 'F' AND emp_id = 123
UNION ALL
SELECT emp_id FROM emp WHERE sex = 'M' AND emp_id = 123;
執行計劃顯示:
SELECT STATEMENT Optimizer=CHOOSE (Cost=6 Card=1 Bytes=5)
SORT (AGGREGATE)
INDEX (SKIP SCAN) OF 'SEX_EMP_ID' (NON-UNIQUE)
| 條件 | 說明 |
|---|---|
| 前導欄位基數極低 | 如性別(2)、狀態碼(<10)、類別(<20)。基數越低,Skip Scan 效益越大。 |
| 後續欄位高基數 | 如 ID、流水號、時間戳,具備高選擇性。 |
| 查詢未包含前導欄位 | WHERE 僅條件後續欄位,或前導欄位為範圍/模糊條件。 |
| 索引較窄 | 聯合索引欄位少、長度短,Skip Scan 讀取塊數可控。 |
效能權衡:
emp_id 查詢頻繁,直接 CREATE INDEX idx_emp_id ON emp(emp_id) 效能最佳。INDEX (SKIP SCAN),並對比 Cost 與邏輯讀。INDEX_SS/NO_INDEX_SS Hint 強制/禁用。Index Skip Scan 是 Oracle 9i 為「低基數前導欄位聯合索引」量身打造的功能,以空間換時間(省去第二個索引)為代價,在無法建立理想索引時提供優於全表掃描的折中方案。設計階段仍應遵循「查詢模式決定索引結構」,Skip Scan 視為補救而非首選。