聚簇索引、非聚簇索引与回表

一、聚簇索引(Clustered Index)

核心特点:索引和数据放在一起,叶子节点直接存整行数据。

InnoDB 里,主键索引就是聚簇索引。

  • B+ 树的叶子节点 存放的是完整的一行数据

  • 找到索引,就等于找到了整行,不需要再回表

类比 :像一本字典,正文本身就是按拼音排序的,你按拼音翻到那一页,字和解释都在那一页。

如果没有主键怎么办?

InnoDB 会这样选聚簇索引:

  1. 有主键 → 用主键

  2. 没主键 → 选第一个唯一非空索引

  3. 都没有 → 自动生成一个隐藏的 row_id 做聚簇索引

所以每张 InnoDB 表一定有且只有一个聚簇索引。

二、非聚簇索引(二级索引 / 辅助索引)

核心特点:索引和数据分开,叶子节点存的是主键值,不是整行数据。

除了聚簇索引,你建的其他索引都是非聚簇索引 (也叫二级索引)。

  • B+ 树的叶子节点 存放的是索引列的值 + 主键值

  • 通过二级索引找到的只是主键,不是完整数据

类比 :像书的目录,目录只告诉你"第 100 页",具体内容还得去正文(聚簇索引)里翻。

举例

表 users:

id(主键) name age
1 张三 20
2 李四 25
  • 聚簇索引 (主键 id):叶子节点存 (1, 张三, 20)、(2, 李四, 25)

  • 非聚簇索引 (在 name 上建索引):叶子节点存 (张三, 1)、(李四, 2),只存 name 和主键 id

三、回表(Back to Table)

回表 = 通过二级索引找到主键后,再拿主键去聚簇索引里查一次完整数据。

什么时候会回表

sql 复制代码
SELECT * FROM users WHERE name = '张三';

执行过程:

  1. 走 name 的二级索引,找到 name = 张三 对应的主键 id = 1

  2. 拿 id = 1 去聚簇索引 里查,拿到整行 (1, 张三, 20)

  3. 返回结果

第 2 步就是回表。

怎么判断有没有回表

用 EXPLAIN 看 Extra:

  • 有 Using index → 用了覆盖索引,不回表

  • 只有 Using where,没有 Using index → 可能回表

四、怎么避免回表:覆盖索引

覆盖索引 :查询需要的列,全都在索引里,不用回表。

sql 复制代码
-- 建联合索引
CREATE INDEX idx_name_age ON users(name, age);

-- 查询列都在索引里
SELECT name, age FROM users WHERE name = '张三';
  • 索引 (name, age) 的叶子节点存 (张三, 20, 1)

  • 查询要的 name、age 都在索引里

  • 直接返回,不用回表

EXPLAIN 里会显示 Extra = Using index。

注意 :如果写成 SELECT *,要的列超出了索引范围,就还是要回表。

相关推荐
白熊--π1 小时前
读懂 Meta API 限流:从范围判断到工程优化
大数据·数据库·meta·facebook
Java爱好狂.1 小时前
Java小白如何三天速通redis?
java·数据库·redis·架构师·分布式锁·java面试·java程序员
菜鸟上路_lbz1 小时前
金仓数据库V9自增id报错
数据库
Novproxy_Z1 小时前
账号批量封禁复盘:从日志定位是 IP 关联还是行为指纹关联
网络·数据库·tcp/ip
我喜欢就喜欢2 小时前
IT疑难杂症诊疗室:从现象到根因的系统排查指南
数据库
其实防守也摸鱼2 小时前
Codex 下载与本地部署实战指南
linux·服务器·前端·数据库·算法·ai
2603_954708312 小时前
如何进一步优化微能网协调控制箱的架构优势
大数据·数据库·人工智能·分布式·架构
瑶山2 小时前
stable-diffusion.cpp 参数全集整理(sd-cli.exe / sd-server.exe)
java·数据库·stable diffusion·参数全集
Pocker_Spades_A2 小时前
一文读懂时序数据库:2026 主流产品全景与六大场景选型(1)
数据库·时序数据库