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

MySQL中的回表是什么?

回表是指在使用非聚簇索引(二级索引)进行查询时,若索引中未包含查询所需的全部数据,需要根据索引中的主键值回到聚簇索引(主键索引)中查找完整数据行的过程。这一操作会增加额外的磁盘 I/O,可能对查询性能产生影响。

举一个例子。比如用户表,id是主键,name有索引。当执行SELECT * FROM users WHERE name='Arm'时,先通过name索引找到对应的id,再用id去主键索引里查整行数据。这时候就发生了两次索引查找,即回表。

select * from user where age = 20;需要根据二级索引(age)找到age = 20的主键键值,然后需要再根据主键去找整行的数据。主键索引频繁查询可能会造成大量随机I/O:

在磁盘上,数据是以数据页为单位进行存储和读取的。如果 age 为 20 的人很多,并且这些记录对应的主键 id 是无序且不连续的,那么在回表过程中,根据这些主键 id 到主键索引中查找记录时,就会需要频繁地访问不同的数据页。例如,一个 age 为 20 的记录对应的主键 id 是 10,下一个 age 为 20 的记录对应的主键 id 可能是 100,这两个 id 对应的记录很可能存储在不同的数据页上。磁盘在读取数据时,磁头需要移动到相应的位置才能读取数据。当需要频繁地访问不同的数据页时,磁头就需要不断地移动,这会带来大量的寻道时间和旋转延迟,也就是随机 I/O。与顺序 I/O 相比,随机 I/O 的性能要差很多,因为顺序 I/O 可以在一次磁头移动过程中连续读取多个数据页,而随机 I/O 每次都需要重新定位磁头,大大增加了磁盘 I/O 的开销。

举例:

假设 user 表中有如下部分数据:

idage
120
520
1520
2520

age 索引中可以快速找到 age 为 20 的记录对应的主键值 151525。但这些主键值在主键索引中对应的记录可能分散在不同的数据页上,例如 id 为 1 的记录在数据页 A,id 为 5 的记录在数据页 B,id 为 15 的记录在数据页 C,id 为 25 的记录在数据页 D。那么在回表时,就需要依次从数据页 A、B、C、D 中读取数据,这就导致了大量的随机 I/O。

所以当 age 为 20 的人很多且主键 id 无序不连续时,回表过程中主键索引的频繁查询会造成大量随机 I/O,从而影响查询性能。

如何避免回表:

可以使用覆盖索引

覆盖索引指索引包含查询所需的所有字段,无需回表即可返回结果:

 -- 查询只需 name 和 age,建立联合索引 (name, age)
 CREATE INDEX idx_name_age ON users(name, age);
 ​
 -- 执行以下查询时,无需回表
 SELECT name, age FROM users WHERE name = '张三';

避免使用 SELECT *,只选择必要的字段:

 -- 避免回表
 SELECT id, name FROM users WHERE name = '张三';
 ​
 -- 需要回表(除非索引覆盖所有字段)
 SELECT * FROM users WHERE name = '张三';

如何判断是否发生了回表

可以通过EXPLAIN命令查看执行计划,如果Extra列显示“Using index”,说明使用了覆盖索引


http://www.kler.cn/a/587506.html

相关文章:

  • Gin(后端)和 Vue3(前端)中实现 Server-Sent Events(SSE)推送
  • [Jenkins] 即将关闭,剩余生成将不会被执行问题解决
  • 支付宝小程序评论提升策略:打造高互动度的用户体验
  • 【NLP】 3. Distributional Similarity in NLP(分布式相似性)
  • 责任链模式如何减少模块之间的耦合
  • starrocks批量启停脚本
  • 生成对抗网络——pytorch与paddle实现生成对抗网络
  • WordPress顶部菜单自定义的方法
  • 酒店宾馆IPTV数字电视系统:创新宾客体验,引领智慧服务新潮流
  • 【蓝桥】模拟
  • Spring Boot整合RabbitMQ极简教程
  • 【小沐学Web3D】three.js 加载三维模型(React)
  • 微信小程序wx.request接口报错(errno: 600001, errMsg: “request:fail -2:net::ERR_FAILED“)
  • 有效封装一个 WebSocket 供全局使用
  • Vue 中如何实现自定义指令?
  • 《DeepSeek 开源 DeepGEMM:开启AI计算新时代的密钥》:此文为AI自动生成
  • 变量赋值汇编
  • 【C】嵌入式的中断,理解
  • Modbus TCP到RTU:轻松转换指南!
  • docker mysql 默认配置文件路径