文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美式 Letter) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


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

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 節「可切換的最佳化」