首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> DB2 資料庫 >> DB2 教學

索引覆蓋與 DB2 查詢效能:優化器為何有時捨棄覆蓋索引?

     編輯:DB2 教學

索引覆蓋的基本概念

當索引包含查詢所需的所有欄位,稱為「索引覆蓋查詢」或「純索引存取」。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、資料分佈),而非單純「是否覆蓋」。深入理解選擇度、資料叢集因子、索引結構與查詢模式的交互作用,才能設計真正高效的索引策略。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved