mysql中非聚簇索引是什么_mysql非聚簇索引基础说明

非聚簇索引叶子节点存储索引列值和主键值,不存整行数据;查询非索引字段需回表;支持覆盖索引避免回表;InnoDB存主键值因数据按主键聚簇,MyISAM存物理地址。

非聚簇索引(也叫二级索引、辅助索引)是 MySQL 中一种将索引与数据物理存储分离的索引结构。它不改变表中数据的实际存放顺序,叶子节点不存完整行记录,而是只存索引列值 + 对应主键值。

非聚簇索引的核心特点

在 InnoDB 引擎中:

  • 每个非聚簇索引的 B+ 树叶子节点,存储的是「索

    引字段值」和「该行对应的主键值」,不是整行数据;
  • 查询时若需要非索引字段(比如 SELECT name FROM user WHERE email = 'a@b.com'),必须先通过 email 索引找到主键 id,再用这个 id 回到聚簇索引树中查出 name —— 这个过程叫「回表」;
  • 一个表可以有多个非聚簇索引,数量上限为 249 个(MySQL 8.0+);
  • 它不占用数据页空间,但会额外消耗磁盘和内存,且每次 INSERT/UPDATE/DELETE 都需同步更新所有相关非聚簇索引。

为什么非聚簇索引要存主键而不是行地址?

InnoDB 的设计决定:数据按主键顺序物理组织(聚簇索引),行位置可能随插入、删除、页分裂而变动。直接存行地址不可靠,而主键稳定唯一,能长期准确指向目标记录。

例如建表:

CREATE TABLE user (id INT PRIMARY KEY, name VARCHAR(32), email VARCHAR(64));

再为 email 建索引:
CREATE INDEX idx_email ON user(email);
此时 idx_email 就是非聚簇索引,其叶子节点内容类似:
[email='a@b.com'] → 主键 id=1024
后续查 SELECT * FROM user WHERE email = 'a@b.com' 就得走两次 B+ 树查找。

哪些情况能避免回表?

当查询语句所需的全部字段,都包含在非聚簇索引中时,就无需回表 —— 这叫「覆盖索引」。

  • SELECT email FROM user WHERE email = 'a@b.com' → 只查索引字段,直接返回;
  • SELECT email, id FROM user WHERE email = 'a@b.com' → id 是主键,已在索引叶子中,仍属覆盖;
  • SELECT email, name FROM user WHERE email = 'a@b.com' → name 不在索引里,必须回表。

MyISAM 和 InnoDB 的非聚簇索引差异

MyISAM 的非聚簇索引叶子节点存的是「行的物理地址(即 .MYD 文件中的偏移量)」,而 InnoDB 存的是「主键值」。这是引擎底层设计的根本区别:MyISAM 数据文件本身无序,InnoDB 数据强制按主键有序。

因此,在 InnoDB 中,主键选择很重要 —— 主键越短(如 INT 而非 UUID),非聚簇索引占用空间就越小,性能损耗也越低。