SQL 聚簇索引与非聚簇索引的差异

12次阅读

聚簇索引是数据的组织方式,叶子节点存整行数据且物理顺序与键值一致;InnoDB中主键索引默认为其,无主键时按非空唯一列或隐藏DB_ROW_ID选取。

SQL 聚簇索引与非聚簇索引的差异

聚簇索引:数据和索引合二为一

聚簇索引不是“一种索引”,而是数据的组织方式。它的核心特点是:**叶子节点直接存整行数据**,数据的物理存储顺序与索引键值顺序完全一致。在 mysql 的 InnoDB 引擎中,主键索引默认就是聚簇索引。这意味着按主键查,一次 B+ 树遍历就能拿到全部字段,无需额外跳转。

如果表没定义主键,InnoDB 会按以下优先级选聚簇索引依据:
– 优先使用一个非空且唯一的索引列;
– 都没有时,自动生成隐藏列 DB_ROW_ID 作为聚簇索引键。

非聚簇索引:索引与数据分离,靠主键“搭桥”

非聚簇索引(也叫二级索引、辅助索引)的叶子节点只存两样东西:**索引列的值 + 对应记录的主键值**。它不改变数据的物理存放位置,因此一张表可以建多个。

用非聚簇索引查数据时,必须走两步:
– 第一步:通过该索引找到主键值;
– 第二步:拿着主键再去聚簇索引里查完整行 —— 这个过程就叫回表

比如对 age 字段建了非聚簇索引,执行 select name FROM user WHERE age = 25,若 name 不在索引里,就得先查到匹配的主键 ID,再回聚簇索引取 name —— 多一次随机 I/O。

关键差异对比

数量限制:每张表只能有一个聚簇索引(物理顺序唯一),但可有多个非聚簇索引。

存储内容
– 聚簇索引叶子节点 = 完整数据行;
– 非聚簇索引叶子节点 = 索引列值 + 主键值(不是指针,是实际主键值)。

查询表现
– 聚簇索引适合范围查询(如 BETWEENORDER BY id)、主键等值查询,数据连续,效率高;
– 非聚簇索引适合精准过滤(如 WHERE status = 'active'),但涉及非索引字段时需回表,开销明显。

维护代价:聚簇索引插入/更新更重——因为要维持物理有序,可能触发页分裂;非聚簇索引更新只需改自己的 B+ 树结构,相对轻量。

一个容易忽略的事实:回表能避免吗?

可以。只要查询所需的所有字段,都包含在非聚簇索引的叶子节点中,就不需要回表。这叫覆盖索引

例如:
– 表有主键 id、字段 nameage
– 建联合索引 (age, name)
– 执行 SELECT name FROM user WHERE age = 25 就能命中覆盖索引,直接返回,不回表。

所以设计索引时,把高频查询的 WHERE 条件字段 放前面,把 SELECT 中要取的字段 放后面,是提升性能的关键思路。

text=ZqhQzanResources