593 字
3 分钟
InnoDB 主键应该如何设计
InnoDB 表按聚簇索引组织,主键选择会影响数据组织和所有二级索引。二级索引叶子记录包含主键值,查询非覆盖字段时再按主键回表。因此主键应稳定、尽量短、非空且不随业务变化;过宽主键会放大每个二级索引的存储和缓存成本。表没有显式主键时,InnoDB 会选择合适的非空唯一索引作为聚簇索引;若没有,则生成隐藏行 ID。
自增整数主键通常插入位置集中在 B+ 树末端,具有较好的局部性,减少随机页分裂;但高并发写入末端页可能形成热点,且分布式多库场景需要全局 ID 方案。随机 UUID 便于生成和跨系统合并,但宽且随机,可能增加索引体积、页分裂和缓存压力。可用有序 UUID 或雪花类 ID,但要评估排序、时钟、唯一性和版本策略,不能只依据名称决定。
主键不是业务展示字段。业务号可能改变、暴露规则或过宽,通常另设唯一业务索引。主键变更代价高,建表前应考虑二级索引数量及未来数据规模。
例如用户表若用邮箱做主键,邮箱变更会牵动聚簇记录定位和相关二级索引,且邮箱字符串会被复制到二级索引条目中。更稳妥的常见设计是短整型或紧凑生成 ID 做主键,再对邮箱建立唯一约束。若需要在多个节点独立生成 ID,应评估时间回拨、节点号分配、排序局部性和冲突处理,并把幂等和唯一键冲突作为应用逻辑的一部分。
追问
- 为什么推荐自增主键? 对常见单库写入,它短且递增,插入局部性较好;这不是所有分布式场景的唯一答案。
- UUID 一定导致随机写吗? 纯随机 UUID 通常如此;有序生成方案可以改善局部性,但有自身生成和兼容边界。
- 二级索引为什么受主键长度影响? 叶子条目要保存主键值作为定位聚簇记录的信息,主键越宽,二级索引往往越大。
目录