什么是索引下推

索引下推(Index Condition Pushdown,ICP)详解


1. 问题背景:联合索引的范围查询限制

假设有一个联合索引 (age, reward),执行以下查询:

SELECT * FROM users WHERE age > 20 AND reward = 100000;
  • 范围查询导致索引部分失效
    由于 age > 20 是范围查询,MySQL 在联合索引中只能使用 age 字段进行筛选,而 reward 字段无法直接通过索引过滤。
  • 传统处理方式的问题
    在 MySQL 5.6 之前,存储引擎层仅根据 age > 20 找到二级索引记录,然后立即回表获取完整数据行,再由 Server 层判断 reward 是否符合条件。这会导致大量无效回表操作,尤其是当 reward = 100000 的记录较少时。

2. 索引下推(ICP)的核心思想

索引下推的核心是将 部分条件过滤 从 Server 层下推到存储引擎层,使得存储引擎在回表前就能过滤掉不符合条件的记录,从而减少回表次数和 IO 开销。


3. 执行流程对比
3.1 不使用索引下推(MySQL 5.6 之前)
  1. 存储引擎层
    • 通过二级索引 (age, reward) 定位到 age > 20 的第一条记录。
    • 获取主键值,回表读取完整数据行。
  2. Server 层
    • 接收完整数据行,检查 reward 是否等于 100000。
    • 若符合条件,返回给客户端;否则丢弃。
  3. 重复过程
    • 存储引擎继续遍历下一条索引记录,重复回表和过滤操作。

问题:即使 reward 不符合条件,仍需回表获取完整数据,导致大量无效 IO。

3.2 使用索引下推(MySQL 5.6+)
  1. 存储引擎层
    • 通过二级索引 (age, reward) 定位到 age > 20 的第一条记录。
    • 直接检查索引中的 reward 字段:若 reward != 100000,跳过该记录;否则回表获取完整数据行。
  2. Server 层
    • 接收过滤后的数据行(仅包含 reward = 100000 的记录)。
    • 进一步检查其他条件(如果有)。
  3. 重复过程
    • 存储引擎继续遍历索引记录,但仅对符合条件的记录回表。

优势:存储引擎层提前过滤无效数据,减少回表次数和 Server 层负载。


4. 索引下推的触发条件
  • 索引类型:仅适用于二级索引(如 InnoDB 的 B+树索引)。
  • 查询条件
    • 条件必须包含联合索引中的列(即使部分列无法直接使用索引)。
    • 例如:WHERE age > 20 AND reward = 100000,即使 reward 无法通过索引直接定位,ICP 仍可过滤。
  • 存储引擎支持:InnoDB 和 MyISAM 均支持。

5. 性能提升示例

假设表中有 100 万条记录:

  • age > 20 的记录有 50 万条,但其中 reward = 100000 的记录仅有 100 条。
  • 无 ICP:需要回表 50 万次,Server 层过滤 50 万次。
  • 有 ICP:存储引擎直接过滤掉 499,900 条记录,仅回表 100 次。

6. 如何确认是否启用了索引下推?

通过 EXPLAIN 查看执行计划,若出现 Using index condition,表示启用了 ICP:

EXPLAIN SELECT * FROM users WHERE age > 20 AND reward = 100000;

输出示例:

+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
| 1  | SIMPLE      | users | NULL       | range | age_reward    | age_reward | 4      | NULL | 5000 | 10.00    | Using index condition |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+

7. 适用场景
  1. 联合索引中的范围查询:例如 WHERE a > 100 AND b = 200
  2. 部分条件无法走索引:例如 WHERE a = 100 AND b LIKE '%abc%',ICP 可过滤 b 的条件。
  3. 高选择性查询:当过滤条件能显著减少回表数据量时,性能提升更明显。

8. 总结
  • 索引下推的本质:将部分条件过滤从 Server 层下沉到存储引擎层。
  • 核心价值:减少回表次数和 Server 层负载,提升查询性能。
  • 限制条件:仅适用于二级索引,且查询条件必须包含索引列。

你可能感兴趣的:(Mysql,android,mysql,数据库,java)