MySQL 5.6 引入的索引優化技術,旨在減少二級索引範圍掃描時的回表次數與Server-Engine 層交互。在索引組織表 (InnoDB) 中,二級索引回表代價高於堆表,ICP 收益顯著。
參考:何登成博士《MySQL 索引條件下推 (ICP) 原理分析》
| 步驟 | 無 ICP | 有 ICP |
|---|---|---|
| 1 | 讀索引元組 → 回表讀完整行 | 讀索引元組 (暫不回表) |
| 2 | Server 層過濾所有 WHERE | 引擎層用索引列過濾 Index Filter 部分 |
| 3 | — | 通過則回表讀完整行 |
| 4 | — | Server 層過濾剩餘 Table Filter 部分 |
EXPLAIN Extra: Using index condition 表示啟用。
-- 索引 (zipcode, lastname, firstname)
SELECT * FROM people
WHERE zipcode='95054'
AND lastname LIKE '%etrunia%'
AND address LIKE '%Main Street%';
zipcode → Index Key。lastname LIKE ... → Index Filter (索引有 lastname,雖無法縮減範圍但可過濾)。address LIKE ... → Table Filter (索引無 address)。
-- 組合索引 (roleId, status, number)
EXPLAIN SELECT * FROM role_goods WHERE roleId=100000001 AND number=1;
+----+------+-----------+------+--------------+----------+---------+-------+------+-----------------------+
| id | type | table | ... | key | key_len | ref | rows | Extra |
+----+------+-----------+------+--------------+----------+---------+-------+------+-----------------------+
| 1 | ref | role_goods| ... | roleId_2 | 9 | const | 14 | Using index condition |
+----+------+-----------+------+--------------+----------+---------+-------+------+-----------------------+
key_len=9 = roleId (BIGINT 8字節) + 1字節 NULL 標誌 → 僅用到 roleId 作為 Index Key (status 缺失導致最左前綴中斷)。Extra: Using index condition 證明 number=1 作為 Index Filter 在引擎層生效,避免了 14 行全部回表。range, ref, eq_ref, ref_or_null。optimizer_switch='index_condition_pushdown=on/off' (默認 on)。