SQL二级索引回表是指查询用二级索引定位后,因索引未覆盖SELECT列而需回聚簇索引查完整行;触发条件是使用二级索引且SELECT列不全被其覆盖;执行分三步:查二级索引得主键、逐主键回聚簇索引取行、汇总返回。

SQL 二级索引回表,是指当查询使用二级索引(非聚簇索引)定位数据后,发现索引中不包含查询所需的所有列,就必须拿着查到的主键值,再回到聚簇索引(主键索引)中查找完整行数据的过程。
回表发生的前提条件
必须同时满足两个条件才会触发回表:
- 查询语句使用了二级索引(比如 WHERE 条件命中了 name、age 等非主键字段上的索引);
- SELECT 列表中存在未被该二级索引覆盖的字段(例如索引只有 age,但查询要 name 和 email)。
回表的具体执行步骤
以表 user(id PK, name, age, city) 和二级索引 idx_age_city(age, city) 为例,执行 SELECT name FROM user WHERE age = 25:
- 第一步:在
idx_age_city的 B+ 树中查找age = 25的叶子节点,拿到匹配记录对应的主键id值列表(如 [101, 205, 318]); - 第二步:对每个
id,单独访问聚簇索引(主键索引),按id查找对应的数据页,读取整行并提取name字段; - 第三步:将所有提取出的
name汇总返回给客户端。
为什么回表会变慢
关键在于 I/O 模式和缓存效率:
- 每次回表都是一次独立的 B+ 树搜索,本质是随机 I/O,不是顺序读;
- 若结果集有数千行,就可能引发同等次数的磁盘寻道(尤其 Buffer Pool 缓存未命中时);
- 主键若为 UUID 或随机值,会导致聚簇索引物理存储离散,进一步放大页跳转开销;
- 大量回表还会挤占 Buffer Pool 空间,降低其他查询的缓存命中率。
如何判断是否正在回表
直接看 EXPLAIN 输出:
- Extra 字段出现 Using where(而非 Using index),大概率发生回表;
-
type 是
ref/range等,但 key 显示用了二级索引,rows 值较大,说明匹配行多、回表压力大; - 用
EXPLAIN FORMAT=JSON查看"using_index": false,明确表示未走覆盖索引。










