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

好的网站标准深圳网站建设 东莞网站建设

好的网站标准,深圳网站建设 东莞网站建设,网站编辑框超链接怎么做,网站举报后还是没封掉引言 作为后端开发或DBA,你是否遇到过这样的场景: 明明给字段加了索引,查询还是慢?EXPLAIN一看,执行计划里type是ref,但数据量不大却耗时很久? 这时候,你很可能遇到了MySQL中常见的…

引言

作为后端开发或DBA,你是否遇到过这样的场景:
明明给字段加了索引,查询还是慢?EXPLAIN一看,执行计划里typeref,但数据量不大却耗时很久?
这时候,你很可能遇到了MySQL中常见的回表查询问题。今天咱们就来扒一扒回表的底层逻辑,以及如何用“覆盖索引”等技巧让它彻底消失!


一、回表是怎么产生的?先搞懂索引的存储结构

要理解回表,得先明白MySQL(以最常用的InnoDB引擎为例)的索引是怎么存的。

1. 聚簇索引:数据的“亲妈”

InnoDB的表数据是按主键顺序物理存储的,这个存储结构就叫聚簇索引(Clustered Index)
简单说:

  • 主键索引的叶子节点里,直接存了整行数据(所有字段的值)。
  • 一张表只能有一个聚簇索引(因为数据只能按一种方式存),没有显式主键的话,InnoDB会自动生成一个隐藏的ROW_ID作为聚簇索引。

2. 二级索引:数据的“替身”

除了主键索引,其他索引(比如普通索引、唯一索引、联合索引)都叫二级索引(Secondary Index)
二级索引的叶子节点比较“精简”——它存的不是整行数据,而是对应的主键ID

举个栗子:
假设我们有个用户表user,结构如下:

CREATE TABLE user (id INT PRIMARY KEY,  -- 主键(聚簇索引)name VARCHAR(20),age INT,INDEX idx_age (age)  -- 二级索引(按age排序)
);

当我们为age字段创建二级索引时,InnoDB会单独建一棵B+树,叶子节点存的是(age值, 主键id)的组合。


二、回表查询:二级索引的“二次寻址”

那问题来了:用二级索引查数据,为啥会触发回表?

场景模拟:一次普通的查询

假设我们要查age=25的所有用户,SQL是:

SELECT * FROM user WHERE age = 25;

执行流程是这样的:

  1. 第一步:扫二级索引找主键ID
    先访问idx_age这棵二级索引树,找到所有age=25的记录,拿到它们的主键ID(比如id=101, 102, 103...)。

  2. 第二步:用主键ID回表查完整数据
    但二级索引的叶子节点只有主键ID,没有完整的用户信息(比如name)。所以,对于每一个找到的主键ID,必须再回到聚簇索引(主键索引树)里,把这行数据的完整内容捞出来。

这个“从二级索引→聚簇索引”的二次查询过程,就是传说中的回表


三、回表有多坑?性能损耗有多大?

回表本身不是错,但如果频繁发生,会让查询变慢!具体损耗在哪?

1. 额外的I/O开销

每次回表都要访问聚簇索引树,而聚簇索引的数据可能分散在不同的磁盘块里。如果回表次数多(比如查1000条记录),就会触发1000次随机I/O——这比顺序读慢100倍!

2. CPU和内存的浪费

每次回表都需要解析聚簇索引的结构,从B+树中定位数据页,再从页里读取完整的行数据。这些操作会消耗CPU和内存资源,尤其是高并发场景下,容易成为瓶颈。

举个对比实验

假设要查100条记录:

  • 无回表(覆盖索引):只需要扫二级索引树,直接拿到所有需要的字段,I/O次数=1次(扫索引树)。
  • 有回表:先扫二级索引树(1次I/O),再扫聚簇索引树100次(100次I/O)。总I/O=101次!

结论:回表次数越多,查询越慢!


四、如何判断是否发生了回表?用EXPLAIN看执行计划

想知道自己的SQL有没有回表,用EXPLAIN命令一看便知!

关键看这两个字段:

  • type:访问类型。如果值是refrange,可能涉及回表(但不绝对)。
  • Extra:额外信息。
    • 如果显示Using index:说明用到了覆盖索引,没回表!
    • 如果显示Using where:说明需要回表后过滤数据(这时候大概率有回表)。

示例演示

假设执行:

EXPLAIN SELECT * FROM user WHERE age = 25;

如果Extra列是空的或显示Using where,说明触发了回表;
如果Extra列显示Using index,说明走了覆盖索引,没回表。


五、回表的终极解法:让查询“原地退休”

既然回表是因为二级索引没存完整数据,那解决思路就简单了:让二级索引直接存查询需要的所有字段,这样就不需要回表了!这就是传说中的覆盖索引

1. 覆盖索引:让索引“自给自足”

覆盖索引的定义是:查询需要的所有字段,都包含在索引中

比如前面的例子,如果我们把索引改成(age, id, name),那么查询SELECT id, age, name FROM user WHERE age=25时:

  • 二级索引的叶子节点已经存了age, id, name,直接就能拿到所有需要的字段,完全不需要回表!

注意:覆盖索引的字段顺序很重要!要把高频查询的条件字段放前面(比如age),返回字段放后面(比如id, name)。

2. 实战技巧:如何设计覆盖索引?

  • 场景1:只查主键
    比如SELECT id FROM user WHERE age=25,这时候二级索引idx_age (age)本身就能覆盖,因为叶子节点存了ageid,无需回表。

  • 场景2:查多个字段
    比如SELECT id, name FROM user WHERE age=25,可以创建联合索引(age, id, name),这样索引直接包含查询字段。

  • 场景3:避免SELECT *
    SELECT *会查询所有字段,如果表有很多字段,很难用覆盖索引。明确指定需要的字段(比如SELECT id, age, name),更容易设计覆盖索引。

3. 进阶优化:索引下推(ICP)

MySQL 5.6之后引入了索引下推(Index Condition Pushdown),能进一步减少回表次数。

原理
原本二级索引扫描时,会把所有符合条件的主键ID先返回给上层,再由上层用ID回表后过滤数据。
而ICP允许把部分过滤条件下推到二级索引层,直接在索引树里过滤掉不满足条件的记录,只返回符合要求的ID,减少回表次数。

开启方式:默认开启(index_condition_pushdown=on),无需额外配置。


六、总结:回表不可怕,优化有方法

回表是MySQL使用二级索引时的正常现象,但它会导致额外的I/O和计算开销。优化的核心是用覆盖索引让查询“原地退休”,避免二次访问聚簇索引。

记住这3个优化步骤

  1. EXPLAIN分析执行计划,确认是否回表(看Extra列)。
  2. 设计覆盖索引,把查询字段和条件字段打包进索引。
  3. 减少SELECT *,明确指定需要的字段。

下次遇到慢查询,先想想是不是回表在作怪!掌握这些技巧,让你的SQL性能飙升~

本文示例基于InnoDB引擎,MyISAM引擎的索引存储结构不同,但回表逻辑类似。

http://www.dtcms.com/wzjs/800283.html

相关文章:

  • 网站轮播图居中代码怎么写设计网站推荐html
  • 手机视频网站怎么做在微信怎样搞做微视频网站
  • 松江车墩网站建设信阳电子商务网站建设
  • 网站建设工资怎么样网页设计期末作品素材
  • 门户网站宣传方案管理咨询公司名称大全
  • jsp手机销售网站的建设wordpress文章内乱码
  • 优秀网站建设模板设计师经常看的app
  • 做视频网站有什么开源阅读app
  • 网站建设优化服务公司经营类网页游戏大全
  • 用vs做网页是怎么创建网站的wordpress修改首页代码
  • 苏州三笑网络科技有限公司东莞百度seo电话
  • 九天智能建站软件电商培训课程
  • asp网站源代码手机网站建设视频教程_
  • 手机网站seo怎么做企业建设高端网站的目的
  • 四川省建设工程信息网站做微商那个网站好
  • 微信小程序格泰网站建设jsp做网站的流程
  • 云海建设工程有限公司网站机械网站案例分析
  • 专业网站开发企业湖北建设厅网站上查询
  • seo常用分析的专业工具如何看出一个网站有做seo
  • 网上做设计网站.网站链接策略
  • 无锡网站营销推广企业门户网站国内外研究现状
  • 石油化工建设网站wordpress更好用吗
  • 旅游网站的系统建设的意义少儿编程哪个品牌好
  • 好的门户网站外贸建站推广
  • 专门找图片素材的网站移动应用开发课程
  • 模具机械东莞网站建设网址查询ip地址方法
  • 哈尔滨网站建设自助建站免费网站开发公司
  • 网站建设规划文档中国产业信息网
  • 住房和建设厅官方网站建网站的公司服务
  • vi毕业设计代做网站智慧服务区下载