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';
复制代码 查询实行过程:
- 先查 idx_name 索引,找到 name='Alice' 对应的 id(假设 id = 3)。
- 再回表查询,根据 id=3 在聚簇索引(主键索引)中找到 address 字段。
为什么要回表? 由于 idx_name 只存了 name 和 id,但 address 不在索引中,必须再回到主键索引查找完整数据。
3. 什么情况下会发生回表?
- 查询的字段不在索引覆盖范围内(即非覆盖索引查询)。
- 使用二级索引(非主键索引)查询,而查询的字段不在索引列中。
4. 怎样避免回表?
(1)使用覆盖索引
如果查询的字段已经包含在索引中,就可以避免回表:
- CREATE INDEX idx_name_age ON users(name, address);
复制代码 然后实行:
- SELECT address FROM users WHERE name = 'Alice';
复制代码 此时,idx_name_age 索引已经包含 name 和 address,以是可以直接在索引中获取数据,不必要回表。
(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 索引已经包含查询字段 |