mysql进阶一

 
 
 

你这个问题问得非常好,很多文章在讲 Index Condition Pushdown(ICP,索引下推) 的时候都举这个例子,但没有解释清楚,导致大家误以为:

“用了联合索引 = 用了 ICP”

实际上,这是两回事。


先说结论

对于:

 
SELECT *
FROM user
WHERE age = 20
AND name LIKE 'Tom%';
 

联合索引:

 
(age, name)
 

确实能用到联合索引。

但是:

是否使用 ICP,关键在于:name LIKE 'Tom%' 这个条件是在“存储引擎层”过滤,还是在“Server 层”过滤。

ICP 优化的是:

 
减少回表次数
 

而不是:

 
决定能不能走索引
 

没有 ICP 的流程

假设:

 
CREATE INDEX idx_age_name ON user(age,name);
 

索引长这样:

 
(age,name)          主键id
--------------------------
20,Tom 1
20,Tommy 2
20,Tony 3
20,Alice 4
20,Bob 5
21,Tom 6
 

查询:

 
SELECT *
FROM user
WHERE age=20
AND name LIKE 'Tom%';
 

MySQL 5.5 以前(没有 ICP):

第一步:

利用联合索引找到:

 
age=20
 

对应范围:

 
20,Tom
20,Tommy
20,Tony
20,Alice
20,Bob
 

第二步:

全部回表:

 
id=1
id=2
id=3
id=4
id=5
 

去聚簇索引找整行数据:

 
SELECT *
 

第三步:

Server 层判断:

 
name LIKE 'Tom%'
 

保留:

 
Tom
Tommy
 

过滤:

 
Tony
Alice
Bob
 

回表次数:

 
5 次
 

有 ICP 的流程

MySQL 5.6+

EXPLAIN:

 
Using index condition
 

表示启用了 ICP。


执行过程:

第一步还是一样:

找到:

 
age=20
 

对应范围:

 
20,Tom
20,Tommy
20,Tony
20,Alice
20,Bob
 

第二步:

因为:

 
name 在联合索引里面
 

所以:

 
name LIKE 'Tom%'
 

可以在二级索引叶子节点上直接判断。

过滤掉:

 
Tony
Alice
Bob
 

保留:

 
Tom
Tommy
 

第三步:

只有符合条件的:

 
id=1
id=2
 

才回表。


回表次数:

 
2 次
 

为什么说是“下推”?

原来:

 
存储引擎

返回所有 age=20 的记录

Server 层

判断 name LIKE
 

变成:

 
存储引擎

判断 age=20
判断 name LIKE

Server 层

拿最终结果
 

即:

 
把原本在 Server 层执行的条件,
下推(Push Down)到存储引擎层执行。
 

所以叫:

 
Index Condition Pushdown
 

你这里真正困惑的是:

既然 (age,name) 本来就能匹配 name,为什么还要 ICP?

答案是:

因为:

 
SELECT *
 

导致:

 
联合索引不是覆盖索引
 

必须回表。

ICP 的意义就在于:

 
先利用索引里的 name 过滤,
再决定哪些记录需要回表。
 

而不是:

 
所有 age=20 的都回表。
 

如果是覆盖索引呢?

例如:

 
SELECT age,name
FROM user
WHERE age=20
AND name LIKE 'Tom%';
 

由于:

 
(age,name)
 

已经覆盖:

 
SELECT age,name
 

执行过程:

 
直接从联合索引返回结果
 

根本:

 
不需要回表
 

此时:

 
ICP 的意义就很小了。
 

EXPLAIN 通常显示:

 
Using where; Using index
 

再举一个更典型的 ICP 场景

索引:

 
(age,name)
 

查询:

 
SELECT *
FROM user
WHERE age > 20
AND name='Tom';
 

没有 ICP:

 
找到所有 age>20


全部回表



Server 判断 name='Tom'
 

有 ICP:

 
找到 age>20



在索引上判断 name='Tom'



只有 Tom 才回表
 

收益更明显。


怎么判断是否用了 ICP?

看:

 
EXPLAIN
SELECT *
FROM user
WHERE age=20
AND name LIKE 'Tom%';
 

如果:

 
Extra:
Using index condition
 

说明:

 
用了 ICP
 

如果:

 
Using where
 

则没有。


最后一句话总结

联合索引决定“能否利用索引定位数据”;ICP 决定“能否利用索引中的字段提前过滤数据、减少回表”。

所以:

 
WHERE age=20
AND name LIKE 'Tom%'
 

(age,name) 上:

  • 联合索引负责找到 age=20 的索引范围;
  • ICP 利用索引中的 name 在回表之前过滤掉不满足 LIKE 'Tom%' 的记录;
  • 最终减少回表次数,提高性能。

这也是为什么很多人会说:

ICP 本质上优化的不是“查索引”,而是“少回表”。

 
 

posted on 2026-07-05 15:41  日思日睿  阅读(8)  评论(0)    收藏  举报