你有没有遇到过这样的情况:查一张几百万行的订单表,加了WHERE条件还带ORDER BY,结果页面卡半天才出来?明明字段上建了索引,为啥还是慢?其实,可能就差一个叫「索引下推」(Index Condition Pushdown,ICP)的优化没打开。
不是所有索引都能“一步到位”
传统做法是:MySQL先用索引快速定位到满足最左前缀的记录位置(比如name='张三'),然后回表取出整行数据,再在Server层逐行判断其他条件(比如age>30 AND city='杭州')。这中间多了一次次磁盘IO——哪怕最后90%的行都被过滤掉了,也得老老实实取出来再扔掉。
索引下推干了啥?
它把部分WHERE条件“塞进”存储引擎层,在利用索引查找过程中就提前做过滤。还是上面的例子:如果联合索引是(name, age, city),那么MySQL可以直接让InnoDB在索引B+树遍历时,用age>30和city='杭州'一起筛,只把真正符合条件的索引项对应的主键拉回来回表。
效果很实在:IO少了,CPU比对少了,响应快了。尤其在高并发查用户列表、商品搜索、后台日志筛选这类场景,提升肉眼可见。
怎么确认它开了没?
执行EXPLAIN看Extra列:
EXPLAIN SELECT * FROM users WHERE name LIKE '王%' AND age > 25 AND city = '深圳';如果看到Using index condition,说明ICP已生效;要是只有Using where,那条件全在Server层过滤,ICP没起作用(可能是索引设计不合理,或MySQL版本太低)。
几点实际提醒
• MySQL 5.6+默认开启,但仅对InnoDB和MyISAM支持;
• 要求索引包含所有用于ICP的字段,否则用不上;
• 不是万能的——如果过滤条件太复杂(比如用了函数、LIKE以%开头),ICP也会自动退化。
下次再调优慢查询,别光盯着加索引,顺手看看执行计划里的Using index condition有没有冒出来。有时候,就是这个小尾巴,悄悄帮你省掉了七八成无效IO。