索引下推(ICP)是MySQL 5.6起引入的优化机制,将WHERE中可由索引字段判断的条件下推至存储引擎层过滤,减少无效回表和I/O。

索引下推(Index Condition Pushdown,简称 ICP)是 MySQL 5.6 起引入的关键查询优化机制,它的核心作用是把 WHERE 条件中**能用索引字段判断的部分**,从 Server 层“下推”到存储引擎层执行过滤,从而大幅减少无效回表和数据传输。
ICP 解决什么问题
没有 ICP 时,查询流程是线性的:存储引擎先按索引条件查出一批索引项 → 全部回表取完整行 → 再由 Server 层逐行应用剩余 WHERE 条件过滤。这会导致大量无意义的磁盘 I/O 和内存开销,尤其当索引匹配范围大、但后续条件过滤性强时(比如 name LIKE '李%' 匹配几千条,而 age = 11 实际只命中几条)。
ICP 把部分条件“提前拦截”在索引扫描阶段,只要索引项里已包含所需字段值(如联合索引中的非前缀列),存储引擎就能当场判断是否满足条件,不满足就跳过回表。
ICP 触发的关键条件
不是所有带索引的查询都能启用 ICP,必须同时满足:
- 使用的是二级索引(普通索引或联合索引),聚簇索引不触发 ICP(叶子节点已是完整行,无需下推)
- WHERE 条件中包含该索引的字段,且至少有一个是非前缀范围条件(如
>、、BETWEEN、LIKE 'abc%') - 查询需要回表(即非覆盖索引查询;若
SELECT字段全在索引中,走覆盖索引,ICP 不生效) - MySQL 版本 ≥ 5.6,且
optimizer_switch中index_condition_pushdown=on(默认开启)
怎么看 ICP 是否生效
执行 EXPLAIN 查看执行计划,重点观察 Extra 列:
- 出现 Using index condition:明确表示 ICP 已启用,存储引擎正在用索引字段做条件过滤
- 同时出现 Using where:说明还有部分条件无法下推(如涉及非索引列、函数、模糊匹配
%xxx等),需 Server 层兜底处理 - 若只有 Using where 没有 Using index condition,大概率 ICP 未触发
怎么让 ICP 效果更好
ICP 的收益高度依赖索引设计与查询写法:
- 优先为高频组合条件建联合索引,并把等值列放前面、范围列放后面(如
(status, create_time, amount)支持WHERE status = 1 AND create_time > '2024-01-01'下推) - 避免在索引字段上使用函数或表达式(如
WHERE YEAR(create_time) = 2024会断掉索引利用,ICP 也失效) - LIKE 查询尽量用前缀匹配(
'abc%'可下推;'%abc'或'%abc%'无法利用索引排序,ICP 不参与) - 确认数据分布——如果某条件过滤性极差(如
gender = 'M'占 49%),即使下推也节省不了多少回表,优化价值有限











