主键索引与唯一索引的区别
主键索引(PRIMARY KEY)和唯一索引(UNIQUE)在 MySQL 中都属于约束型索引——既有唯一性约束作用,也具备索引加速查询的能力。但两者存在本质区别。
核心区别对比
| 对比维度 | 主键索引(PRIMARY KEY) | 唯一索引(UNIQUE) |
|---|---|---|
| =NULL 值= | ❌ 不允许 NULL(任何列) | ✅ 允许 NULL,且允许多个 NULL |
| 每表数量 | 最多 1 个 | 可 多个 |
| 聚簇性质 | InnoDB 中 主键即聚簇索引 | 二级索引(非聚簇索引) |
| 约束层级 | 实体完整性约束(Entity Integrity) | 唯一性约束(Unique Constraint) |
| 是否可以由外键引用 | ✅ 可以 | ❌ 不能直接引用 |
| 索引类型 | 按数据存储方式分类 | 按功能逻辑分类 |
1. NULL 值处理:最根本的差异
CREATE TABLE test (
id INT PRIMARY KEY,
email VARCHAR(100) UNIQUE
);
INSERT INTO test(id, email) VALUES (1, NULL); -- ✅ 唯一索引允许 NULL
INSERT INTO test(id, email) VALUES (2, NULL); -- ✅ 允许第二个 NULL(NULL ≠ NULL)
INSERT INTO test(id, email) VALUES (3, 'a@b.com'); -- ✅
INSERT INTO test(id, email) VALUES (4, 'a@b.com'); -- ❌ ERROR: Duplicate entrySQL 标准中 NULL 的含义
NULL 不等于任何值,甚至不等于另一个 NULL。 因此在唯一索引中,多个 NULL 值并不违反唯一性约束。而在主键中,NULL 表示”未知”,违背了”每一行必须能被唯一标识”的实体完整性原则。
2. 聚簇性质:InnoDB 的特有关联
在 InnoDB 存储引擎中:
-
主键索引 = 聚簇索引(Clustered Index)
- 叶子节点直接存储完整行数据,数据按主键顺序物理组织
- 决定了表数据的物理存储排列,因此一个表只能有一个主键
-
唯一索引 = 二级索引(Secondary Index)
- 叶子节点存储主键值,而非完整行数据
- 查询需要两步:先通过唯一索引找到主键值,再回聚簇索引取数据(除非被覆盖索引覆盖)
graph TB subgraph 聚簇索引(主键) PK["id: int (PK) → 整行数据"] end subgraph 二级索引(唯一索引) UK["email: varchar (UNIQUE) → id: int (PK)"] end UK -->|"回表(如果必要)"| PK
性能影响
因为唯一索引是二级索引,每次通过唯一索引查询时,可能涉及回表操作。而主键索引直接定位到数据行,通常更快。使用覆盖索引可以消除唯一索引的回表开销。
3. 主键选择策略
推荐使用自增/序列主键
CREATE TABLE user (
id BIGINT AUTO_INCREMENT PRIMARY KEY, -- ✅ 推荐的聚簇索引
email VARCHAR(100) UNIQUE,
name VARCHAR(50)
);- B+Tree 的新插入操作只在当前最右侧叶子节点追加,页分裂概率低
- 逻辑递增,保持聚簇索引的物理顺序连续性
不推荐使用业务字段做主键
-- ❌ 不推荐:用身份证号、手机号作为主键
CREATE TABLE user (
id_card VARCHAR(18) PRIMARY KEY,
name VARCHAR(50)
);- 业务字段长度长,导致二级索引体积大(二级索引存主键值)
- 业务字段可能变更,但主键不应变更
- UUID 做主键尤其不推荐:离散插入导致频繁页分裂、空间碎片
UUID 主键问题
UUID 字符串长(36 字节)、无序插入,会造成 B+Tree 频繁页分裂、数据碎片化、二级索引臃肿。若业务需要唯一标识,可考虑 UUID 作为唯一索引 + AUTO_INCREMENT 整数作主键的分离策略。
4. 语义和使用场景
| 场景 | 应使用 |
|---|---|
| 唯一标识每行记录 | 主键 |
| 保证业务字段不重复(如手机号、邮箱) | 唯一索引 |
| 需要外键引用 | 主键 |
| 允许 NULL 的唯一性约束 | 唯一索引 |
| 接口幂等性中的去重表 | 唯一索引 + 业务流水号 |
相关笔记
- MySQL索引类型 — 索引分类总览
- MySQL索引创建原则 — 创建索引的注意事项
- 接口幂等方案设计 — 唯一索引在幂等性中的应用
- 事务ACID — 实体完整性与 ACID 的关系