Oracle 9i 新特性。當**複合索引前導欄位不在 WHERE 條件中**,但**前導欄位 Distinct Values 極少**時,CBO 可選擇「邏輯分割」索引為多個子索引,逐一掃描,避免全表掃描。
(col1, col2, ...),查詢條件**不含 col1**,含 col2...。/*+ INDEX_SS(t idx) */。Oracle 邏輯上將索引分割為 NDV(col1) 個子索引,每個子索引對應一個 col1 值。掃描成本 ≈ NDV(col1) × 子索引掃描成本。若此成本 < FTS 成本,則選擇 ISS。
環境:TEST1(A NUMBER, B CHAR(10), C VARCHAR2(10)),索引 TEST_IDX1(A, B),10 萬筆資料。
INSERT INTO test1 SELECT MOD(ROWNUM,37), TO_CHAR(ROWNUM), TO_CHAR(ROWNUM) FROM DUAL CONNECT BY LEVEL <= 100000;
ANALYZE TABLE test1 COMPUTE STATISTICS;
SELECT * FROM test1 WHERE b = '500';
-- Plan: TABLE ACCESS FULL (Cost=37)
TRUNCATE TABLE test1;
INSERT ... MOD(ROWNUM,36) ...;
ANALYZE ...;
SELECT * FROM test1 WHERE b = '500';
-- Plan: INDEX (SKIP SCAN) OF TEST_IDX1 (Cost=12)
-- FTS Cost 仍為 37,ISS Cost=12 < 37,故選擇 ISS
結論:在該資料量/區塊大小下,**NDV ≤ 36 觸發 ISS,NDV ≥ 37 退回 FTS**。門檻值 = **FTS Cost**。
| 查詢 | Cardinality 預估 | 計劃 | 說明 |
|---|---|---|---|
WHERE b <= '1' | 1 | INDEX SKIP SCAN | 低基數,ISS 勝出 |
WHERE b <= '10' | 773 | TABLE ACCESS FULL | 高基數導致 ISS 成本 > FTS |
WHERE a>=0 AND b <= '1' | 1 | INDEX SKIP SCAN | 加上前導欄位條件 (涵蓋全域) 仍走 ISS |
NDV(A)=100,000 (唯一值),查詢 WHERE b='500':
SELECT * → FTS (Cost=37)SELECT COUNT(*) → INDEX FAST FULL SCAN (Cost=34)SELECT a → INDEX FAST FULL SCAN (Cost=34) — 索引覆蓋查詢RULE Hint → FTS (RBO 不支援 ISS)