SMD:支持 Spotify、Deezer、YouTube 等多平台的音乐下载工具
2026/6/26 4:05:26
在学习MySQL过程中,阅读到这样一段话:在 MySQL 中,B+ 树索引按照存储方式的不同分为聚集索引和非聚集索引。我就在想为什么要分为这两种,下面我就详细介绍这两者的联系、优缺点。
二者是强绑定的,InnoDB 的设计逻辑里,非聚集索引完全依赖聚集索引:
| 对比维度 | 聚集索引 | 非聚集索引 |
|---|---|---|
| 叶子节点存储 | 存储整行数据 | 存储索引列的值+聚集索引的主键值 |
| 索引体积 | 体积大(等于表的实际数据体积) | 体积小(仅包含索引列和主键,远小于表体积) |
| 访问效率 | 1. 主键查询/范围查询效率极高 2.非主键查询效率极低(需要全表扫描) | 1. 非主键查询(匹配索引列)效率极高 2.覆盖索引场景下,效率优于聚集索引 3.非覆盖场景需回表,效率略降 |
| 排序特性 | 天然按主键排序,无需额外排序 | 可按索引列排序,避免ORDER BY触发的文件排序 |
| 创建限制 | 1. 一张表仅能创建1个聚集索引 2.默认以主键为聚集索引;无主键则选唯一非空索引;否则生成隐藏rowid | 1. 一张表可创建多个非聚集索引 2.支持基于任意字段/联合字段创建 |
| 更新代价 | 更新主键(聚集索引键)会导致整行数据移动,代价极高 | 更新索引列仅修改索引树节点,代价低;若索引列是主键,会联动修改所有非聚集索引 |
我们用一个电商的订单表(order_info)来举例,表结构如下:
CREATETABLE`order_info`(`order_id`BIGINTNOTNULLCOMMENT'订单ID(主键,聚集索引)',`user_id`BIGINTNOTNULLCOMMENT'用户ID',`order_time`DATETIMENOTNULLCOMMENT'下单时间',`order_amount`DECIMAL(10,2)NOTNULLCOMMENT'订单金额',`order_status`TINYINTNOTNULLCOMMENT'订单状态',PRIMARYKEY(`order_id`),-- 聚集索引KEY`idx_user_time`(`user_id`,`order_time`)-- 非聚集联合索引)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;场景 1:适合用聚集索引的场景
如果运营需要查询「订单 ID 为 100001 的订单的所有信息」,SQL 如下:
SELECT*FROMorder_infoWHEREorder_id=100001;场景 2:适合用非聚集索引(覆盖索引)的场景
如果运营需要查询「用户 ID 为 1001 的所有订单的下单时间和订单金额」,SQL 如下:
SELECTorder_time,order_amountFROMorder_infoWHEREuser_id=1001;场景 3:适合用非聚集索引(需要回表)的场景
如果运营需要查询「用户 ID 为 1001 的所有订单的完整信息」,SQL 如下:
SELECT*FROMorder_infoWHEREuser_id=1001;