【MySQL 索引优化黑科技】什么是索引下推?
在做 MySQL 查询优化时,你可能看到过执行计划中出现过这样一行:
Extra: Using index condition
这到底是什么意思?是不是索引失效?还是反而更快?
一、什么是索引下推(ICP)?
一句话定义:
索引下推是 MySQL 5.6 引入的一项优化技术,用于减少回表次数,提高查询性能。
传统情况下,当普通索引匹配到主键 id 时,如果查询还有其他条件,MySQL 会:
-
1. 根据二级索引定位到主键 id -
2. 去主键索引回表 -
3. 再判断其他 WHERE 条件是否满足
如果 WHERE 有多个条件,但索引只匹配了部分,剩下的条件原本只能回表后检查。
索引下推的优化点是:
把更多 WHERE 条件尽可能 提前放到索引层判断,过滤掉不符合的数据,避免不必要的回表。
二、为什么索引下推能更快?
直接一句话:
减少回表次数 = 减少磁盘 IO = 性能暴涨
回表是最耗时的操作之一,因为要回到主键索引再次查整行数据。
如果能提前过滤掉无效记录,性能提升非常明显。
三、举例理解:为什么 ICP 能提升性能?
假设有索引:
INDEX(name, age)
SQL:
SELECT * FROM user
WHERE name LIKE 'T%' AND age > 30;
传统方式(无 ICP):
-
1. 使用索引找到所有 name LIKE 'T%' 的主键 id -
2. 全部回表 -
3. 再判断 age > 30
如果 name 开头 T 的人有 10 万条,那么 10 万次回表 = 💔 性能炸裂。
加上 ICP 后:
-
1. 索引定位 name LIKE 'T%' -
2. 在索引层过滤 age > 30 -
3. 只回表少数满足条件的记录
👉 回表次数从 10 万次降到 100 次,性能提升可以达到 1000 倍。
这就是索引下推的威力!
四、哪些条件可以参与索引下推?
规则很简单:
✔ 可以下推:
-
• 参与索引的字段 -
• 范围条件、比较条件、部分 like -
• 联合索引的后续字段
如:
WHERE name LIKE 'T%' AND age > 30
name 是索引前缀,首先精确定位前缀;age > 30 能在索引中“提前过滤”。
❌ 不可以下推:
-
• 使用函数的字段 -
• 不在索引上的字段 -
• OR 条件复杂、无法分解的情况
例如:
WHERE UPPER(name) = 'TOM' AND age > 20
UPPER(name) 无法利用索引,也无法下推。
五、如何判断 SQL 是否启用了索引下推?
只需要看 EXPLAIN:
EXPLAIN SELECT * FROM user WHERE name LIKE 'T%' AND age > 30;
如果 Extra 出现:
Using index condition
恭喜!ICP 生效了。
如果只是:
Using where; Using index
则没有使用索引下推。
六、如何让索引下推生效?
很简单:
✔ 1. 使用联合索引
比如:
INDEX(name, age)
✔ 2. WHERE 条件尽量按照最左前缀原则写
比如 name 然后 age。
✔ 3. 避免对索引字段使用函数
比如:
WHERE LEFT(name, 1) = 'T' -- ❌
WHERE name LIKE 'T%' -- ✔
七、总结
索引下推(ICP)是 MySQL 5.6 引入的一项查询优化技术,它将部分 WHERE 条件提前下放到索引扫描阶段,从而减少回表次数,提高查询性能。
ICP 可以在索引层先过滤掉不符合条件的数据,只对少量匹配记录回表,比传统方式更高效。
它通常用于联合索引的后续字段,对范围条件、比较条件都有效,但对函数处理字段或不在索引上的字段无法生效。
当执行计划中出现“Using index condition”,说明索引下推已被启用。
👉 索引下推 = 索引中用更多条件过滤数据 = 少回表 = 性能飞起
👉 一旦 EXPLAIN 出现“Using index condition”,这是好事!

