SQL 二级索引如何回表?

11次阅读

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

SQL 二级索引如何回表?

SQL 二级索引回表,是指当查询使用二级索引(非聚簇索引)定位数据后,发现索引中不包含查询所需的所有列,就必须拿着查到的主键值,再回到聚簇索引(主键索引)中查找完整行数据的过程。

回表发生的前提条件

必须同时满足两个条件才会触发回表:

  • 查询语句使用了二级索引(比如 WHERE 条件命中了 name、age 等非主键字段上的索引);
  • SELECT 列表中存在未被该二级索引覆盖的字段(例如索引只有 age,但查询要 nameemail)。

回表的具体执行步骤

以表 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),大概率发生回表;
  • typeref/range 等,但 key 显示用了二级索引,rows 值较大,说明匹配行多、回表压力大;
  • EXPLAIN format=jsON 查看 "using_index": false,明确表示未走覆盖索引。
text=ZqhQzanResources