← 返回题目列表

MySQL 中聚簇索引和二级索引有什么区别?

高频 中等 第 11 / 28 题 更新于 2026/07/29
MySQLInnoDB聚簇索引二级索引

简化版

InnoDB 的聚簇索引通常就是主键索引,叶子节点保存整行数据;二级索引叶子节点保存二级索引列和主键值,查询非覆盖字段时需要再按主键回表。

详细版

聚簇索引决定数据行的物理组织方式。在 InnoDB 中,一张表的数据按主键 B+ 树组织,主键索引叶子节点就是完整行数据。

二级索引也使用 B+ 树,但它的叶子节点不直接保存完整行,而是保存二级索引键和对应主键值。比如 idx_name(name) 查到 name='Tom' 后,若还要读取 ageaddress 等不在索引里的列,就需要拿主键再去聚簇索引查一次,这叫回表。

面试回答要带出三个点:InnoDB 表数据和主键索引绑定;二级索引通过主键定位整行;主键设计会影响所有二级索引的空间和查询成本。

完整版教学

一、为什么叫聚簇索引

聚簇索引的意思是“数据行和索引放在一起”。在 InnoDB 中,主键索引的叶子节点保存整行记录。

可以这样理解:

主键 B+ 树
非叶子节点:主键范围导航
叶子节点:id + name + age + address + ...

所以根据主键查一行通常非常直接:

SELECT * FROM users WHERE id = 100;

数据库沿主键 B+ 树找到叶子节点,就拿到了整行数据。

记忆钩子:聚簇索引叶子节点就是数据,二级索引叶子节点只是通往数据的路标。

二、二级索引叶子节点保存什么

二级索引是除聚簇索引之外的普通索引、唯一索引等。在 InnoDB 中,二级索引叶子节点保存的是“索引列 + 主键值”。

例如:

CREATE TABLE users (
  id BIGINT PRIMARY KEY,
  name VARCHAR(50),
  age INT,
  city VARCHAR(50),
  INDEX idx_name(name)
);

idx_name 的叶子节点近似是:

name='Alice' -> id=10
name='Bob'   -> id=18
name='Tom'   -> id=25

如果查询 SELECT id, name FROM users WHERE name='Tom',二级索引本身已经有 nameid,可能不需要回表。如果查询 SELECT city FROM users WHERE name='Tom',就要拿 id=25 回到聚簇索引读取 city

三、什么是回表

回表就是“先走二级索引找到主键,再走聚簇索引取整行或缺失列”。

SELECT city
FROM users
WHERE name = 'Tom';

执行路径:

idx_name 二级索引:name='Tom' -> id=25
聚簇索引:id=25 -> 读取 city

如果命中 1 行,回表成本不明显;如果命中 10 万行,每一行都要回表,随机访问成本就可能很高。

这也是为什么覆盖索引能优化查询:如果所需字段都在二级索引里,就不用再回到聚簇索引。

四、主键为什么会影响二级索引

因为每个二级索引叶子节点都保存主键值,所以主键越大,二级索引越占空间。

假设一张表有 1000 万行、5 个二级索引:

主键类型主键长度二级索引额外保存成本
BIGINT8 字节较小
CHAR(36) UUID36 字节明显更大
长字符串64 字节以上成本更高

这还只是空间成本,页中能容纳的索引项变少后,B+ 树高度和缓存命中率也可能受影响。

因此 InnoDB 常建议使用短小、稳定、尽量递增的主键,尤其是写入量大、二级索引多的业务表。

五、没有主键时 InnoDB 怎么办

InnoDB 优先使用主键作为聚簇索引。如果没有显式主键,会选择第一个非空唯一索引;如果也没有合适唯一索引,InnoDB 会生成隐藏 row id 作为聚簇索引键。

流程可以记成:

显式 PRIMARY KEY
-> 第一个 NOT NULL UNIQUE KEY
-> 隐藏 row id

隐藏 row id 对业务不可见,不利于查询和维护。工程上不建议依赖它,最好为表设计明确主键。

如果业务天然有稳定唯一字段,也要考虑是否适合作为主键。例如手机号会变更,身份证号敏感且较长,很多时候使用业务无关的自增或雪花 id 更可控。

六、聚簇索引对范围查询和插入的影响

主键顺序决定数据在聚簇索引中的排列。递增主键插入通常追加到 B+ 树右侧,页分裂较少;随机 UUID 主键会把新记录插入到各个位置,可能造成页分裂和缓存抖动。

范围查询也会受益于聚簇索引顺序:

SELECT *
FROM orders
WHERE id BETWEEN 100000 AND 100100;

因为叶子节点按主键有序链接,范围扫描可以顺序读取相邻叶子页。若按随机主键写入,数据逻辑顺序仍然有序,但插入维护成本更高。

这就是主键设计题经常和聚簇索引一起考的原因。

七、常见误区与追问

  • 误区:聚簇索引就是一种普通索引。 在 InnoDB 中它同时组织整行数据,和表数据强绑定。
  • 误区:二级索引叶子节点保存整行数据。 InnoDB 二级索引叶子节点保存索引列和主键值,不保存完整行。
  • 误区:所有二级索引查询都会回表。 如果查询字段被索引覆盖,就可以不回表。
  • 误区:主键长度只影响主键索引。 二级索引叶子节点也保存主键,主键长度会影响所有二级索引。
  • 追问:为什么不建议随机 UUID 做 InnoDB 主键? 它较长且插入位置随机,可能增加页分裂、空间占用和缓存压力。
  • 追问:没有主键时会怎样? InnoDB 会尝试选非空唯一索引,否则生成隐藏 row id,但工程上应显式设计主键。

八、加强记忆

聚簇索引题抓住“一棵树存整行,二级索引存主键”。主键查直接到数据,二级索引查常要回表;主键既决定行组织方式,又进入每个二级索引,所以主键设计会影响查询、空间和写入成本。