Index First Key / Index Last Key。MySQL 5.6 前:Index Filter 與 Table Filter 不分離,範圍內所有索引條目全部回表 → Server 層過濾。
MySQL 5.6+:Index Filter 下推到存儲引擎層 (InnoDB/MyISAM),引擎層利用索引列直接過濾,僅將滿足 Index Filter 的行回表,大幅減少回表次數與 Server-Engine 交互開銷。
ICP = Index Filter 技術的工程落地。因 MySQL 架構分 Server/Engine 兩層,故稱「下推」。
| 階段 | 無 ICP | 有 ICP |
|---|---|---|
| 1 | 讀索引元組 → 回表讀完整行 | 讀索引元組 (不回表) |
| 2 | Server 層過濾 WHERE | 引擎層用索引列過濾 Index Filter 部分 |
| 3 | 返回結果 | 通過則回表讀完整行 → Server 層過濾 Table Filter 部分 → 返回 |
EXPLAIN 的 Extra 列顯示 Using index condition 表示啟用 ICP。
range, ref, eq_ref, ref_or_null。optimizer_switch='index_condition_pushdown=on/off' (默認 on)。
-- 索引 INDEX (zipcode, lastname, firstname)
SELECT * FROM people
WHERE zipcode='95054'
AND lastname LIKE '%etrunia%'
AND address LIKE '%Main Street%';
zipcode 為 Index Key (確定範圍)。lastname LIKE '%etrunia%' 無法用於範圍縮減,但可作為 Index Filter (索引中有 lastname 列)。address LIKE ... 索引中無此列,屬 Table Filter。
-- 組合索引 INDEX (roleId, status, number)
EXPLAIN SELECT * FROM role_goods WHERE roleId=100000001 AND number=1;
輸出:key_len=9 (roleId 8字節 + 1字節 NULL 標誌),Extra: Using index condition。
status 缺失,number 無法成為 Index Key (最左前綴中斷)。number 存在於索引中,ICP 使其成為 Index Filter,引擎層直接過濾 number=1,避免回表。ICP 是 MySQL 5.6 重要優化特性,零代碼修改、零配置風險 即可自動受益。核心價值:將原本在 Server 層的索引列過濾下推到引擎層,減少回表與網絡/內存拷貝開銷。對於大量二級索引範圍掃描且有部分索引列可過濾的查詢,效果顯著。