面试题:MySQL 的索引下推是什么?

MySQL 的索引下推(Index Condition Pushdown,简称 ICP)是什么?

索引下推是 MySQL 5.6 引入的一种查询优化技术,其核心目的是减少回表查询的次数,从而提升查询效率。它通过将部分 WHERE 条件的判断逻辑下推到存储引擎层,在索引扫描阶段就完成过滤,避免将大量不符合条件的数据返回给 Server 层处理。


传统查询流程 vs 索引下推流程

传统查询流程(无 ICP)

  1. 索引扫描:存储引擎通过二级索引(如联合索引)找到符合条件的记录主键。
  2. 回表查询:根据主键回表到聚簇索引中获取完整数据行。
  3. Server 层过滤:将完整数据行返回给 MySQL Server 层,再根据 WHERE 条件进行过滤。

问题:即使某些记录在索引中就能判断不符合条件,仍需回表查询完整数据,导致无效的 IO 操作。


索引下推流程(启用 ICP)

  1. 索引扫描与过滤并行:存储引擎在遍历二级索引时,直接对 WHERE 条件中能通过索引字段判断的部分进行过滤(例如联合索引中的字段)。
  2. 减少回表:只有满足索引条件的记录才会回表查询完整数据行。
  3. Server 层最终过滤:对回表后的数据行应用剩余的过滤条件(如非索引字段的条件)。

优势:减少回表次数,降低 IO 开销,提升查询性能。


适用场景与条件

  1. 联合索引的使用
    • 例如,对联合索引 (name, age) 查询时,WHERE name LIKE '张%' AND age = 10
    • 存储引擎在索引扫描时直接判断 age = 10,跳过不符合条件的记录。
  2. 范围查询或模糊查询
    • 例如,WHERE key_part1 > x AND key_part2 = y 或 WHERE key_part1 LIKE 'abc%'
  3. 版本要求
    • 仅适用于 MySQL 5.6 及以上版本,且支持 InnoDB 和 MyISAM 存储引擎。
  4. 限制条件
    • 不能用于主键索引(聚簇索引),因为主键索引的叶子节点已包含完整数据。
    • WHERE 条件中的字段必须出现在索引中,否则无法下推。

示例分析

假设有一个用户表 user,联合索引为 (name, age),执行以下查询:

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

无 ICP 的流程

  1. 存储引擎通过联合索引 (name, age) 找到所有 name LIKE '张%' 的记录(如 id=1,4)。
  2. 回表查询 id=1 和 id=4 的完整数据。
  3. Server 层再过滤 age = 20,最终返回符合条件的记录。

启用 ICP 后的流程

  1. 存储引擎在遍历联合索引时,直接判断 age = 20
  2. 只有 age = 20 的记录(如 id=1)才会回表查询。
  3. Server 层无需额外过滤,直接返回结果。

索引下推的效果

  • 减少回表次数:从多次回表减少到仅对符合条件的记录回表。
  • 降低 IO 开销:避免读取大量无效数据行。
  • 提升性能:尤其在过滤条件选择性高(如 age = 20)时效果显著。

如何验证索引下推是否生效?

通过 EXPLAIN 命令查看执行计划的 Extra 字段:

  • 无 ICPUsing where; Using index condition 未出现。
  • 启用 ICPExtra 字段显示 Using index condition

示例:

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

输出:

| id | select_type | table | type  | possible_keys | key      | key_len | ref  | rows | Extra              |
|----|-------------|-------|-------|---------------|----------|---------|------|------|--------------------|
| 1  | SIMPLE      | user  | range | index_name    | index_name | 478     | NULL | 100  | Using index condition |

总结

  • 索引下推的核心价值:通过在存储引擎层提前过滤数据,减少回表次数,提升查询效率。
  • 适用场景:联合索引 + 范围查询/模糊查询 + WHERE 条件字段在索引中。
  • 注意事项:需 MySQL 5.6+,不适用于主键索引,且对非索引字段的条件无法下推。
THE END
喜欢就支持一下吧
点赞14 分享