NULL
值(隐式 NOT NULL
约束)。ROW_ID
作为聚集索引。NULL
值(MySQL特性,与SQL标准不同,其他数据库如Oracle/SQL Server仅允许单个NULL
)。email
+ phone
+ national_id
)。UNIQUE NOT NULL
索引作为聚集索引。ROW_ID
竞争(如组提交时影响InnoDB事务性能)。BIGINT UNSIGNED AUTO_INCREMENT
,无业务意义且紧凑。特性 | 主键索引 | 唯一索引 |
---|---|---|
NULL 允许 | ❌ 绝对禁止 | ✅ 允许多个NULL(MySQL特性) |
数量限制 | 每表仅1个 | 可创建多个 |
索引类型 | 必定为聚集索引 | 默认为非聚集索引 |
是否强制 | 推荐显式定义,否则自动生成隐藏主键 | 完全可选,按需添加 |
外键关联 | 默认被引用 | 可显式指定为外键引用目标 |
存储内容 | 包含完整数据行(聚集索引) | 存储索引列+主键值(需回表查询) |
典型用例 | 数据表核心标识(如user_id ) |
业务防重(如email 、order_no ) |
主键设计原则
唯一索引陷阱
WHERE email = NULL
无法命中索引,需用IS NULL
。UNIQUE(a,b)
可支持a=?
查询,但无法单独用b=?
。性能调优
INCLUDE
或联合索引减少回表,如SELECT user_id FROM users WHERE email='xxx'
可利用唯一索引直接返回。-- 显式定义自增主键
CREATE TABLE users (
user_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, -- 聚集索引
email VARCHAR(255) NOT NULL,
phone VARCHAR(20),
UNIQUE KEY uk_email (email), -- 唯一索引
UNIQUE KEY uk_phone (phone) -- 允许phone为NULL且存在多条NULL
);
-- 外键引用唯一索引
CREATE TABLE orders (
order_id VARCHAR(32) PRIMARY KEY, -- 自然主键(需确保绝对唯一)
user_id BIGINT UNSIGNED,
FOREIGN KEY (user_id) REFERENCES users(user_id)
);
最终结论:主键是数据组织的基石,唯一索引是业务规则的守护者。设计时应严格区分两者用途,主键追求极致稳定和高效,唯一索引则需贴合业务防重需求。