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

3-001:MySQL 中的回表是什么?

1. 什么是回表?

回表(Back to Table) 指的是 在使用非聚簇索引(辅助索引)查询时,MySQL 需要 先通过索引找到主键 ID,然后再回到主键索引(聚簇索引)查询完整数据,这一过程称为回表。


2. 回表的示例

假设有一张 users 表:

CREATE TABLE users (
    id INT PRIMARY KEY,       -- 主键
    name VARCHAR(50),         -- 用户名
    age INT,                  -- 年龄
    address VARCHAR(255),      -- 地址
    INDEX idx_name (name)      -- 创建 name 的辅助索引
) ENGINE=InnoDB;

如果执行以下查询:

SELECT address FROM users WHERE name = 'Alice';

查询执行过程:

  1. 先查 idx_name 索引,找到 name='Alice' 对应的 id(假设 id = 3)。
  2. 再回表查询,根据 id=3 在聚簇索引(主键索引)中找到 address 字段。

为什么要回表? 因为 idx_name 只存了 nameid,但 address 不在索引中,必须再回到主键索引查找完整数据。


3. 什么情况下会发生回表?

  • 查询的字段不在索引覆盖范围内(即非覆盖索引查询)。
  • 使用二级索引(非主键索引)查询,而查询的字段不在索引列中。

4. 如何避免回表?

(1)使用覆盖索引

如果查询的字段已经包含在索引中,就可以避免回表

CREATE INDEX idx_name_age ON users(name, address);

然后执行:

SELECT address FROM users WHERE name = 'Alice';

此时,idx_name_age 索引已经包含 nameaddress,所以可以直接在索引中获取数据,不需要回表

(2)使用主键查询

如果使用 id(主键)查询,就不需要回表:

SELECT address FROM users WHERE id = 3;

因为 InnoDB 的主键索引(聚簇索引)本身就存储了完整数据,所以查询 id 不会回表。


5. 总结

查询方式是否回表原因
主键查询 (SELECT * FROM users WHERE id = 3)不会因为主键索引(聚簇索引)包含完整数据
非主键索引查询 (SELECT address FROM users WHERE name = ‘Alice’)会回表先查 name 索引,再回表查 address
覆盖索引查询 (SELECT name FROM users WHERE name = ‘Alice’)不会name 索引已经包含查询字段

🚀 结论: MySQL InnoDB 避免回表的方法

  1. 尽量使用覆盖索引(让查询的所有字段都包含在索引中)。
  2. 使用主键查询,避免使用非主键索引查询非索引字段。
  3. 分析 EXPLAIN 结果,关注 Extra 字段是否包含 "Using index"(表示使用了覆盖索引)。

这样可以减少回表,提高查询性能!🚀

6. 拓展:二级索引的叶子节点和非叶子节点存储内容**

6.1 二级索引 B+ 树结构示意

假设有如下 users 表:

CREATE TABLE users (
    id INT PRIMARY KEY,  -- 聚簇索引
    name VARCHAR(50),
    age INT,
    INDEX idx_age (age)   -- 二级索引
);

其中,表中的数据如下:

idnameage
1Alice25
2Bob30
3Charlie35

6.2 完整的二级索引 B+ 树结构
                (30)
               /    \
           (25)      (35)
         /      \     /    \
    (age=25,id=1) (age=30,id=2) (age=35,id=3)
6.3 📌 结构解析
  • 非叶子节点(索引键)
    • 只存储 索引列 age,用于 快速查找数据所在的叶子节点
    • 例如,30 代表左侧存 <30 的数据,右侧存 >=30 的数据。
  • 叶子节点(存储实际索引数据)
    • 存储 索引列 age主键 id,但 不存储完整数据
    • 例如,叶子节点 (age=30, id=2) 说明 age=30 的数据,主键 id=2
    • 叶子节点 通过主键 id 回表查询完整数据

6.4 二级索引查询流程

查询 SELECT * FROM users WHERE age = 30;

  1. 从非叶子节点找到 30 对应的叶子节点。
  2. 叶子节点存储 (age=30, id=2),返回 id=2。
  3. 回表:用 id=2 查询 users 表的主键索引,获取完整数据。

6.5 🔥 关键点总结
  1. 非叶子节点 只存索引 key(age),不存储数据
  2. 叶子节点age主键 ID,用于返回 ID 进行回表查询。
  3. 回表查询 是因为 二级索引不存完整数据,需要用主键 ID 进一步查询。
  4. 优化方式:
    • 覆盖索引(例如 INDEX idx_age_name (age, name)),让查询字段直接存入索引,避免回表。
    • 合理设计主键,避免主键过大影响二级索引的存储效率。

这样,你对二级索引的 存储结构和查询流程 是否更加清晰了呢? 😊🚀

相关文章:

  • 中国软件供应链安全技术指南|DevSecOps敏捷安全技术金字塔V3.0正式发布
  • MQ消息发送不在MySQL事务中,该如何保证一致性?
  • 蓝桥 2109统计子矩阵
  • Ubuntu22.04安装数据
  • 5.1 程序调试
  • 什么是双机热备系统?双机热备现在是否已经过时了?
  • 职坐标C语言数据结构算法核心精讲
  • Deep research深度研究:ChatGPT/ Gemini/ Perplexity/ Grok哪家最强?(实测对比分析)
  • 内容中台的实施基石是什么?
  • vue2双向绑定解析
  • 单片机设计暖脚器研究
  • 投资晚报 3.12
  • 【论文笔记】FLARE:feed-forward+posegeometry estimate+GS
  • 调优案例一:堆空间扩容提升吞吐量实战记录
  • 适合二次开发的Web组态软件推荐
  • 子母钟系统,京准电子科技助力高考精准计时
  • 机器学习常见激活函数
  • Vitis IDE 艰难切换--从传统 Vitis GUI 到 2024.1 统一软件界面
  • NetAssist 5.0.14网络助手基础使用及自动应答使用方案
  • 【学习笔记】《逆向工程核心原理》03.abex‘crackme-2、函数的调用约定、视频讲座-Tut.ReverseMe1
  • 消费持续升温,这个“五一”假期有何新亮点?
  • 体坛联播|曼联一只脚迈进欧联杯决赛,赵心童4比4奥沙利文
  • 山西太原小区爆炸事故已造成17人受伤
  • 济南高新区一季度GDP增长8.5%,第二产业增加值同比增长14.4%
  • 辽宁辽阳火灾3名伤者无生命危险
  • 游客曝九寨沟打网约车被出租车围堵,景区回应:当地无合规网约车