面试官:什么是覆盖索引?

MySQL 索引里有一个经常被问到的问题:

明明已经走了索引,为什么还需要回表?

之前讲过,回表就是在二级索引查到主键之后,再拿主键去聚簇索引把整行数据捞回来的那一步。

它本质上是在二级索引中找到主键后,再根据主键到聚簇索引中查询完整记录,因此会增加额外的索引访问和数据页读取成本。

那问题来了------有没有可能走了索引,但不需要回表

有,这就是覆盖索引。

覆盖索引是什么

覆盖索引,指的是:

查询语句需要的所有字段,都已经在某个索引里找到了,不需要再回聚簇索引拿数据。

一次索引查询就拿到了所有需要的数据,没有二次查找。

为什么能实现?

InnoDB 的二级索引叶子节点,存的不只是索引字段的值,还有对应的主键值。

所以当查询的字段都在这个索引里,这条路径就被"覆盖"了。

举个容易理解的例子。

二级索引像图书馆的目录卡,上面写着书名和对应的书架号(主键)。

聚簇索引像书架上摆好的整本书(整行数据)。

如果目录卡上已经印着作者、出版年份这些你需要的信息,你就不必跑回书架去翻书------目录卡自己就够了。

这就是覆盖索引。

一个实际场景

假设有一张订单表:

sql 复制代码
CREATE TABLE `order` (
  order_id INT PRIMARY KEY,
  user_id INT,
  create_time DATETIME,
  status INT,
  amount DECIMAL(10, 2),
  INDEX idx_user_id (user_id)
);

order_id 是主键,对应聚簇索引。

user_id 是普通索引,叶子节点存的是 (user_id, order_id)

现在有这么一条查询:

sql 复制代码
SELECT order_id, create_time
FROM `order`
WHERE user_id = 12345;

这条 SQL 需要的是 order_idcreate_time 两个字段。

如果走 idx_user_id 索引,二级索引叶子节点里虽然有 user_idorder_id,但 没有 create_time

拿到 order_id 之后,还得拿着它去聚簇索引把 create_time 捞回来。

这中间,就多了一次回表。

怎么改成覆盖

思路很直接:

让索引自己把结果给全,不需要再去聚簇索引里捞。

怎么做到?

user_id 上加一个复合索引,把 create_time 也包含进去:

sql 复制代码
ALTER TABLE `order` ADD INDEX idx_user_time (user_id, create_time);

加了索引之后,查询走 idx_user_time 这棵 B+ 树,叶子节点保存了 user_idcreate_time,同时 InnoDB 的二级索引叶子节点还会保存对应的主键值 order_id

查到 user_id = 12345 时,直接返回 order_idcreate_time,不需要再回聚簇索引。

这就是覆盖索引的优化效果:

查询所需的数据都能直接从二级索引中获取,不需要再回表。

覆盖索引的边界

不是所有查询都能被覆盖。

有几个判断标准,值得在心里过一遍。

查询的字段必须全在索引里。

如果 SQL 里还选了个 status 字段,而索引里没有 status,那还是得回表。

覆盖是有条件的,不能无限扩大。

索引要贴合查询需求。

在满足查询条件的基础上,如果查询结果、排序或过滤所需的字段能够合理地包含在索引中,就有机会减少回表、排序等额外操作。

多列索引会占用更多存储空间,写入时也要维护索引,成本会上升。

因此,要结合查询收益、写入压力和索引大小综合判断,别为了覆盖而乱加索引。

最后串一下

覆盖索引的核心,就是"索引自己能把结果给全,不用再去聚簇索引里捞数据"。

它的前提是:

查询所需的字段都能够从索引中获取。

对于 InnoDB 的二级索引来说,主键值本身也会存储在二级索引叶子节点中,因此查询主键通常也可以被覆盖。

覆盖索引减少了从二级索引回到聚簇索引的访问,因此通常可以减少额外的页访问和 CPU 开销。

建索引不是越多越好,覆盖索引只是优化手段之一。

相关推荐
林太白1 小时前
What did Trea work help me with in this optimization process
前端·后端
Asize1 小时前
3 种设计模式 + DI:Nest.js 后端第一课
后端·设计模式·nestjs
程序员cxuan1 小时前
一招教你在 Codex 中开启 1M 上下文
人工智能·后端·程序员
IT_陈寒2 小时前
Vite热更新失效?八成是这个配置在搞鬼
前端·人工智能·后端
qq_22589174662 小时前
基于Flask的空气质量监测与预测分析系统
开发语言·后端·python·信息可视化·django·flask
覆东流2 小时前
4.Java运算符与表达式
java·开发语言·后端
马丁玩编程2 小时前
GitHub 3.5k Star 之后,Ragent AI 框架新版本来了
后端·面试·github
微石科技2 小时前
医疗设备维保如何从被动维修转向预防管理?宁波微石科技让运行数据提前发信号
java·后端·struts
AINative软件工程2 小时前
LLM 应用的 Warm-Up 工程实践:冷启动延迟从 12 秒砍到 800ms 的 5 个工程手段
后端·llm·ai编程