MySQL中的回表是什么?

打印 上一主题 下一主题

主题 1078|帖子 1078|积分 3234

回表是指在利用非聚簇索引(二级索引)进行查询时,若索引中未包含查询所需的全部数据,需要根据索引中的主键值回到聚簇索引(主键索引)中查找完整数据行的过程。这一操纵会增加额外的磁盘 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 表中有如下部分数据:
idage12052015202520 在 age 索引中可以快速找到 age 为 20 的记载对应的主键值 1、5、15、25。但这些主键值在主键索引中对应的记载大概分散在不同的数据页上,例如 id 为 1 的记载在数据页 A,id 为 5 的记载在数据页 B,id 为 15 的记载在数据页 C,id 为 25 的记载在数据页 D。那么在回表时,就需要依次从数据页 A、B、C、D 中读取数据,这就导致了大量的随机 I/O。
以是当 age 为 20 的人许多且主键 id 无序不一连时,回表过程中主键索引的频仍查询会造成大量随机 I/O,从而影响查询性能。
怎样制止回表:
可以利用覆盖索引
覆盖索引指索引包含查询所需的所有字段,无需回表即可返回结果:
  1.  -- 查询只需 name 和 age,建立联合索引 (name, age)
  2.  CREATE INDEX idx_name_age ON users(name, age);
  3.  ​
  4.  -- 执行以下查询时,无需回表
  5.  SELECT name, age FROM users WHERE name = '张三';
复制代码
制止利用 SELECT *,只选择必要的字段:
  1.  -- 避免回表
  2.  SELECT id, name FROM users WHERE name = '张三';
  3.  ​
  4.  -- 需要回表(除非索引覆盖所有字段)
  5.  SELECT * FROM users WHERE name = '张三';
复制代码
怎样判断是否发生了回表
可以通过EXPLAIN命令查察执行计划,假如Extra列显示“Using index”,阐明利用了覆盖索引

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

笑看天下无敌手

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表