Skip to content

P28 聚集索引和非聚集索引 ​

面试题:什么是聚集索引(聚簇索引)和非聚集索引(二级索引)?有什么区别?

1. 核心定义 ​

  • 聚集索引(Clustered Index):数据行直接存储在索引的叶子节点上。InnoDB 中主键索引就是聚集索引,"索引即数据,数据即索引";
  • 非聚集索引(二级索引/辅助索引):叶子节点存的是索引列的值 + 主键值,不直接存整行数据。

2. InnoDB 的两种索引 ​

聚集索引(主键索引) ​

text
B+ 树叶子节点 = 完整数据行
  • 表必须有一个聚集索引:
    • 有主键 → 主键就是聚集索引;
    • 没主键 → 选第一个非空唯一索引;
    • 都没有 → 隐藏生成 rowid 作为聚集索引;
  • 数据行按主键顺序物理存储(逻辑上)。

二级索引(普通索引/联合索引) ​

text
B+ 树叶子节点 = (索引列的值, 主键值)

通过二级索引查数据需要回表:先用二级索引找到主键,再到聚集索引里查整行。

3. 区别对比 ​

对比项聚集索引非聚集索引
叶子节点整行数据索引列 + 主键
数量每表最多一个每表可以多个
查询数据直接得到整行一般需回表
插入性能主键乱序插入会页分裂相对独立
覆盖索引本身就是覆盖索引列覆盖查询时可免回表

4. 高频追问 ​

① 什么是回表(回表查询) ​

text
SELECT * FROM t WHERE name = 'x';   -- name 是二级索引
二级索引查到主键 → 聚集索引再查一次 → 回表

② 什么是覆盖索引 ​

查询的列全部在二级索引里,就不用回表:

sql
SELECT id, name FROM t WHERE name = 'x';
-- name 索引 = (name, id),id/name 都在索引里 → Using index,免回表

③ 为什么 InnoDB 二级索引叶子存主键而不是行指针 ​

主键不变,数据页移动/分裂时二级索引无需更新;若存行指针,数据搬迁会导致大量索引失效。

④ 主键为什么要用自增/有序的 ​

聚集索引按主键有序存储,乱序主键(UUID)插入会导致频繁页分裂、索引碎片、性能下降。

一句话总结 ​

聚集索引叶子存整行(InnoDB 主键索引),非聚集索引叶子存"索引列+主键";二级索引查数据通常要回表,用覆盖索引可以免回表,主键设计要有序以保插入性能。

基于 VitePress 重建