当前位置: 首页 > news >正文

什么是索引下推和索引覆盖?

一、索引下推(Index Condition Pushdown, ICP)

1. 什么是索引下推?
  • 核心思想:在存储引擎层(如 InnoDB)提前过滤数据,减少不必要的回表操作。
  • 通俗解释:假设你有一个联合索引,查询时部分条件可以直接在索引层过滤掉不符合条件的记录,而不是把数据全部交给 MySQL 服务层再过滤。
2. 例子:没有索引下推 vs 有索引下推

假设有一张用户表 users,包含以下字段:

CREATE TABLE users (
    id INT PRIMARY KEY,
    age INT,
    city VARCHAR(20),
    name VARCHAR(20),
    INDEX idx_age_city (age, city)
);

现在执行查询:

SELECT * FROM users 
WHERE age > 20 AND city = 'Beijing';
情况1:没有索引下推(ICP关闭)
  1. 存储引擎的工作
    • 使用索引 idx_age_city,找到所有 age > 20 的记录。
    • 将这些记录的主键 id 返回给 MySQL 服务层。
  2. 服务层的工作
    • 根据主键 id 回表查询完整数据(包括 city)。
    • 再过滤出 city = 'Beijing' 的记录。

问题:存储引擎返回了大量 age > 20city 不是 Beijing 的记录,导致服务层需要回表并处理大量无用数据。

情况2:有索引下推(ICP开启)
  1. 存储引擎的工作
    • 使用索引 idx_age_city,直接过滤 age > 20 city = 'Beijing' 的记录。
    • 只返回满足两个条件的主键 id
  2. 服务层的工作
    • 根据主键 id 回表查询完整数据。

优化效果:存储引擎提前过滤了 city = 'Beijing',减少了回表次数和服务层处理的数据量。

3. 如何验证 ICP?

执行 EXPLAIN 查看执行计划:

EXPLAIN SELECT * FROM users 
WHERE age > 20 AND city = 'Beijing';

如果 Extra 列显示 Using index condition,说明 ICP 生效。

4. 适用场景
  • 查询条件包含联合索引中的列和非索引列(但非索引列过滤由存储引擎完成)。
  • 例如:联合索引 (a, b),查询条件为 a > 10 AND b = 'x' AND c = 'y',其中 c 是非索引列,但 b 的过滤可以下推。

二、索引覆盖(Covering Index)

1. 什么是索引覆盖?
  • 核心思想:查询所需的所有列都包含在索引中,无需回表查询主键索引。
  • 通俗解释:就像查字典时,你要查的单词和解释都在目录里,不需要翻到正文页。
2. 例子:没有索引覆盖 vs 有索引覆盖

继续使用 users 表,索引为 idx_age_city (age, city)

情况1:没有索引覆盖

查询:

SELECT * FROM users 
WHERE age = 25;
  • 流程
    1. 使用索引 idx_age_city 找到 age = 25 的记录的主键 id
    2. 根据 id 回表查询主键索引,获取所有字段(id, age, city, name)。
  • 问题:需要回表获取 name 字段,增加 I/O 操作。
情况2:有索引覆盖

查询:

SELECT age, city FROM users 
WHERE age = 25;
  • 流程
    1. 直接通过索引 idx_age_city 获取 agecity 的值。
    2. 无需回表查询主键索引。

优化效果:减少 I/O 和 CPU 消耗。

3. 如何验证索引覆盖?

执行 EXPLAIN

EXPLAIN SELECT age, city FROM users 
WHERE age = 25;

如果 Extra 列显示 Using index,说明索引覆盖生效。

4. 适用场景
  • 查询的列全部在索引中。
  • 例如:索引 (a, b, c),查询 SELECT a, b FROM table WHERE c = 10(需注意索引顺序是否能覆盖)。

三、联合使用案例

场景:同时利用 ICP 和索引覆盖

users 有索引 idx_age_city (age, city),执行查询:

SELECT id, age, city FROM users 
WHERE age > 20 AND city = 'Beijing';
  1. 索引覆盖id(主键)、agecity 都在索引 idx_age_city 中,无需回表。
  2. 索引下推:存储引擎直接过滤 age > 20city = 'Beijing',减少数据传输。

通过 EXPLAIN 可以看到:

  • Extra 列显示 Using index condition; Using index,说明同时用到了 ICP 和索引覆盖。

四、通俗总结

1. 索引下推(ICP)
  • 比喻:快递分拣员在仓库里直接扔掉不符合条件的包裹(如收件地址错误),而不是把所有包裹送到分拣中心再处理。
  • 核心:在存储引擎层提前过滤数据,减少“无效包裹”的传递。
2. 索引覆盖
  • 比喻:查字典时,目录里直接写了单词的解释,不需要翻到正文页。
  • 核心:避免回表查询,直接从索引中获取所有需要的数据。

五、注意事项

  1. 索引设计
    • 索引下推依赖联合索引的列顺序。
    • 索引覆盖要求查询的列全部在索引中。
  2. 性能权衡
    • 索引过多会影响写入性能。
  3. 验证工具
    • 使用 EXPLAIN 查看执行计划,重点关注 Extra 列。

六、实际应用建议

  1. 高频查询:优先为高频查询设计覆盖索引。
  2. 联合索引顺序:将过滤条件多的列放在索引前面。
  3. 减少回表:尽量通过覆盖索引避免 SELECT *

相关文章:

  • 06-SpringBoot3入门-常见注解(简介)
  • 《破局摩尔定律:AI驱动、异构集成与工具革新重构芯片效能新范式》
  • Redis数据迁移同步
  • 乳腺超声图像结节分割
  • LeetCode算法题(Go语言实现)_15
  • 煤矿油田光伏管理新突破:安科瑞分布式监控系统如何破解高耗能行业转型难题
  • 深度学习框架PyTorch——从入门到精通(9)PyTorch简介
  • 机试题——村落基站建设
  • Java 集合中ArrayList与LinkedList的性能比较
  • Visual Studio 2022中打开其他项目的步骤
  • 虚拟货币和 Token
  • 剑指Offer26 -- 树
  • ‘无法定位程序输入点kernel32.dll’详细的修复方法,一键快速修复kernel32.dll
  • 瑞芯微RK356X主板复用接口配置方法,触觉智能嵌入式方案商
  • 使用ModbusRTU读取松下测高仪的高度
  • CORDIC算法:三角函数的硬件加速革命——从数学原理到FPGA实现的超高效计算方案
  • d2025328
  • LAC自动建立L2TP
  • 如何做管理
  • Python Random 模块使用完全指南
  • 这位中国电影早期的全能奇才,90年前唱响国歌
  • 一周观展|一批重量级考古博物馆开馆:从凌家滩看到孙吴大墓
  • 四大皆空!赛季还没结束,曼城已经吃上“散伙饭”了
  • 著名文博专家吴远明因交通事故离世,享年75岁
  • 贞丰古城:新垣旧梦间的商脉与烟火
  • 俄乌官员即将在土耳其会谈,外交部:支持俄乌开启直接对话