文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (美國信件) - 40.0Mb
PDF (A4) - 40.1Mb
手冊頁 (TGZ) - 258.2Kb
手冊頁 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  索引條件下推最佳化

10.2.1.6 索引條件下推最佳化

索引條件下推 (ICP) 是一種最佳化,適用於 MySQL 使用索引從資料表擷取資料列的情況。在沒有 ICP 的情況下,儲存引擎會遍歷索引以找到基底資料表中的資料列,並將它們傳回 MySQL 伺服器,後者會評估資料列的 WHERE 條件。啟用 ICP 後,如果 WHERE 條件的部分可以使用索引中的資料行來評估,則 MySQL 伺服器會將 WHERE 條件的這部分下推到儲存引擎。然後,儲存引擎會使用索引條目評估下推的索引條件,並且僅在滿足此條件時才從資料表中讀取資料列。ICP 可以減少儲存引擎必須存取基底資料表的次數,以及 MySQL 伺服器必須存取儲存引擎的次數。

索引條件下推最佳化的適用性受限於以下條件

  • 當需要存取完整的資料表資料列時,ICP 用於 rangerefeq_refref_or_null 存取方法。

  • ICP 可以用於 InnoDBMyISAM 資料表,包括分割的 InnoDBMyISAM 資料表。

  • 對於 InnoDB 資料表,ICP 僅用於輔助索引。ICP 的目標是減少完整資料列的讀取次數,進而減少 I/O 操作。對於 InnoDB 叢集索引,完整的記錄已經讀入 InnoDB 緩衝區。在這種情況下使用 ICP 並不會減少 I/O。

  • 在虛擬產生欄位上建立的輔助索引不支援 ICP。InnoDB 支援虛擬產生欄位上的輔助索引。

  • 參考子查詢的條件無法下推。

  • 參考儲存函數的條件無法下推。儲存引擎無法調用儲存函數。

  • 觸發條件無法下推。(有關觸發條件的資訊,請參閱第 10.2.2.3 節「使用 EXISTS 策略最佳化子查詢」。)

  • 條件無法下推至包含系統變數參考的衍生資料表。

若要了解此最佳化如何運作,請先考慮當未使用索引條件下推時,索引掃描如何進行

  1. 取得下一列,首先讀取索引元組,然後使用索引元組定位並讀取完整資料表列。

  2. 測試適用於此資料表的 WHERE 條件部分。根據測試結果接受或拒絕該列。

使用索引條件下推,掃描會改為這樣進行

  1. 取得下一列的索引元組(但不是完整資料表列)。

  2. 測試適用於此資料表且僅可使用索引欄位檢查的 WHERE 條件部分。如果條件不滿足,則繼續處理下一列的索引元組。

  3. 如果條件滿足,則使用索引元組定位並讀取完整資料表列。

  4. 測試適用於此資料表的 WHERE 條件的其餘部分。根據測試結果接受或拒絕該列。

當使用索引條件下推時,EXPLAIN 輸出會在 Extra 欄位中顯示 Using index condition。它不會顯示 Using index,因為當必須讀取完整資料表列時,該訊息不適用。

假設有一個資料表包含關於人員及其地址的資訊,且該資料表定義了一個索引 INDEX (zipcode, lastname, firstname)。如果我們知道某個人的 zipcode 值,但不確定姓氏,我們可以這樣搜尋

SELECT * FROM people
  WHERE zipcode='95054'
  AND lastname LIKE '%etrunia%'
  AND address LIKE '%Main Street%';

MySQL 可以使用索引掃描 zipcode='95054' 的人員。第二部分 (lastname LIKE '%etrunia%') 無法用於限制必須掃描的資料列數量,因此如果沒有索引條件下推,此查詢必須檢索所有 zipcode='95054' 的人員的完整資料表列。

使用索引條件下推,MySQL 會在讀取完整資料表列之前檢查 lastname LIKE '%etrunia%' 部分。這避免了讀取符合 zipcode 條件但不符合 lastname 條件的索引元組對應的完整資料列。

索引條件下推預設為啟用。可以使用設定 optimizer_switch 系統變數中的 index_condition_pushdown 旗標來控制它

SET optimizer_switch = 'index_condition_pushdown=off';
SET optimizer_switch = 'index_condition_pushdown=on';

請參閱第 10.9.2 節「可切換的最佳化」