索引下推(ICP,Index Condition Pushdown)
**索引下推ICPIndex Condition Pushdown**是 MySQL 5.6 默认开启的优化把 WHERE 里能在索引上判断的条件下推到存储引擎层在遍历索引时就过滤掉不满足条件的行从而大幅减少回表次数和 I/O。下面用最清晰、面试可直接背的方式讲。一、一句话理解没有 ICP只按索引最左前缀过滤 → 所有匹配前缀的都要回表→ Server 层再过滤 → 大量无效回表。有 ICP索引里有的字段条件在索引阶段就过滤→ 只回表那些真正符合全部条件的 →回表变少、性能变快。图书馆类比好记索引目录姓名、年龄、书架号查姓名张三 AND 年龄20无 ICP把所有“张三”的目录都拿出来逐个去书架拿书再看年龄是不是20。有 ICP直接在目录里筛出“张三年龄20”只拿这几本去书架。二、原理与流程必背假设有联合索引idx(a,b,c)SQLselect*fromtwherea1andb2andclikex%;1无 ICPMySQL 5.6 前Server 层给存储引擎条件a1。存储引擎扫描索引找出所有a1的索引项 →全部回表拿整行。Server 层再过滤b2 and c like x%→ 很多白回表。2有 ICP默认开启Server 层把a1 and b2 and c like x%一起下推给存储引擎。存储引擎遍历索引时直接在索引上判断 a、b、c。只有全部条件满足的索引项才去回表拿整行。无效行在索引阶段就丢掉不回表、不浪费 I/O。执行计划标志EXPLAIN中Extra显示Using index condition→ 正在使用 ICP。三、生效条件面试常问MySQL5.6默认开启optimizer_switchindex_condition_pushdownon。引擎InnoDB / MyISAM不支持全文索引。索引联合索引最左前缀匹配。WHERE 条件部分字段在索引里且不是主键、不是函数/表达式。访问类型range / ref / eq_ref / ref_or_null。四、ICP vs 覆盖索引区别必背覆盖索引Using index查询列全在索引里→完全不回表直接从索引拿数据。索引下推Using index condition必须回表如select *但尽量少回表。一句话覆盖索引 不回表索引下推 少回表五、优化示例直接能用表user(name, age, city)联合索引idx_name_age_city(name,age,city)慢 SQL无 ICP 效果select*fromuserwherename张三andcity北京;索引最左前缀name张三无 ICP所有name张三都回表 → Server 过滤city北京有 ICP索引里有city直接在索引过滤 →回表大幅减少。开启/关闭 ICP-- 开启默认setoptimizer_switchindex_condition_pushdownon;-- 关闭测试用setoptimizer_switchindex_condition_pushdownoff;六、总结面试直接背ICP 作用减少回表次数降低磁盘 I/O提升查询性能。核心原理将索引字段的过滤条件下推到存储引擎在索引遍历阶段过滤。生效场景联合索引、条件字段在索引中、InnoDB/MyISAM。与覆盖索引区别覆盖索引不回表ICP 减少回表。