當索引包含查詢所需的所有欄位,稱為「索引覆蓋查詢」或「純索引存取」。DB2 優化器通常會選擇僅存取索引,避免讀取資料頁面。但「通常」不代表「總是」——優化器以總成本最低為目標,有時會捨棄覆蓋索引而選擇非覆蓋索引。
CREATE TABLE CONTACT (
ZIPCODE INT NOT NULL,
PHONE_NUMBER CHAR(10) NOT NULL,
SOME_OTHER_STUFF VARCHAR(100)
);
CREATE INDEX CONTACT_ZIP_PHONE ON CONTACT (ZIPCODE, PHONE_NUMBER);
CREATE INDEX CONTACT_PHONE ON CONTACT (PHONE_NUMBER);
SELECT ZIPCODE, PHONE_NUMBER
FROM CONTACT
WHERE PHONE_NUMBER LIKE '312987654%' AND ZIPCODE = '60606';
雖然 CONTACT_ZIP_PHONE 覆蓋查詢欄位,但優化器選擇 CONTACT_PHONE。原因在於選擇度差異:
ZIPCODE='60606' 符合 >15,000 列(低選擇度)PHONE_NUMBER LIKE '312987654%' 符合 ≤10 列(高選擇度)使用 CONTACT_PHONE:讀 2 個索引頁(根+葉)+ 10 個資料頁 = 總成本極低。
若強制使用 CONTACT_ZIP_PHONE:需掃描 '60' 到 '61' 範圍,讀取 >100 個葉級頁面,成本高得多。
此原則在大多數情況正確。但若查詢模式固定(如常查 WHERE ZIPCODE='60606' 無電話條件),則 (ZIPCODE, PHONE_NUMBER) 索引優於 (PHONE_NUMBER, ZIPCODE),因前者可直接定位 ZIPCODE 範圍,後者需全索引掃描。
效能差異不純粹基於選擇度,而是「不同欄位對應的資料列在資料頁面的物理分佈」。高選擇度索引返回的少量資料列可能分散於大量資料頁(隨機 I/O 多);低選擇度索引返回的大量資料列可能集中在少數頁面(循序 I/O 多)。實測為準。
RUNSTATS 統計資訊與 EXPLAIN 驗證索引覆蓋是強大的效能優化手段,但優化器決策基於總成本模型(I/O、CPU、資料分佈),而非單純「是否覆蓋」。深入理解選擇度、資料叢集因子、索引結構與查詢模式的交互作用,才能設計真正高效的索引策略。