大家好,欢迎来到IT知识分享网。
哈喽,你好啊,我是雷工!
最近在研究数据库设计表格时,用到主键的设计。
由于没有系统的学习过相关知识,一时不知道该如何设计主键,
于是遇事不决问AI,决定通过问AI的形式学习一下该如何设计主键,并避免重复策略。
01 如何提问
问题如下:
设计数据库时主键该如何设计,用什么作为主键,而且如何避免重复?

02 解决方案
以下是AI给出的回答:
设计数据库主键是一个核心问题,直接影响数据完整性、查询性能、扩展性和维护性。以下是主键设计的核心原则、常见方案以及避免重复的策略:
一、主键的核心要求
- 唯一性:在整个表中绝对唯一,不能重复。
- 非空性:不能为 NULL。
- 稳定性:值一旦生成,最好永不改变(避免外键引用失效)。
- 简洁性:尽量短小(利于索引效率和外键存储)。
- 简单性:最好是单一字段(非强制,但复合主键会增加复杂度和外键引用难度)。

二、常见主键设计方案及优缺点
方案 |
优点 |
缺点 |
适用场景 |
1. 自增整数 (AUTO_INCREMENT / SERIAL) |
✅ 简单易用<br>✅ 存储空间小<br>✅ 索引效率高<br>✅ 天然保证唯一性 |
��� 无业务含义<br>❌ 分库分表时需额外处理<br>❌ 易暴露数据量<br>❌ 插入前无法预知ID |
单机/简单系统、OLTP 核心表、不关心业务含义的场景 |
2. UUID/GUID |
✅ 全局唯一(跨库/跨服务器)<br>✅ 生成无需依赖数据库<br>✅ 隐藏数据量 |
❌ 存储空间大 (32字符)<br>❌ 索引效率低(随机写入)<br>❌ 无序性导致页分裂 |
分布式系统、需要提前生成ID、数据合并场景 |
3. 雪花算法 (Snowflake ID) |
✅ 全局唯一、大致有序<br>✅ 存储空间适中 (64-bit)<br>✅ 高性能 |
❌ 实现复杂(需维护机器ID)<br>❌ 依赖系统时钟(时钟回拨问题) |
高并发分布式系统、需要全局有序ID的场景 |
4. 业务主键 (Natural Key) |
✅ 有业务含义<br>✅ 可读性强<br>✅ 可能减少关联查询 |
❌ 可能变更(违反稳定性)<br>❌ 可能过长<br>❌ 组合键复杂<br>❌ 唯一性难保证 |
编码规则严格且不变的场景(如身份证号、ISBN) |
5. 混合方案 (业务键+代理键) |
✅ 平衡业务需求和稳定性 |
❌ 增加冗余字段<br>❌ 设计稍复杂 |
既需业务标识又需稳定主键的场景 |
三、如何避免主键重复 – 关键策略
- 使用数据库自增机制:
- AUTO_INCREMENT (MySQL), SERIAL (PostgreSQL), IDENTITY (SQL Server), Sequence (Oracle, PostgreSQL)。
- 优点:数据库内部保证唯一性,绝对可靠。
- 缺点:仅适用于单库或主从复制环境,分布式环境下需特殊方案(如设置不同初始值/步长 – 不推荐)。
- 使用标准化全局唯一生成器:
- UUID/GUID:使用标准库生成(如 UUID.randomUUID())。理论上重复概率极低(2^128),可认为唯一。
- 雪花算法 (Snowflake):确保机器ID(workerId)在集群内唯一,解决时钟回拨问题(时钟回拨可能导致重复)。
- Redis 自增:利用 Redis 的原子操作 INCR 生成集群范围内唯一的序列号。
- 数据库 Sequence 服务:专门提供分布式 ID 生成服务(如 TDDL Sequence、Leaf)。
- 业务主键的严格校验:
- 数据库唯一约束:在业务字段上创建 UNIQUE 约束,作为最后防线。
- 应用层校验:插入/更新前检查该业务值是否存在(注意并发问题!需结合数据库唯一约束)。
- 预生成与分配:由中心系统按规则生成并分配业务主键值(如订单号生成服务)。
- 分布式数据库的特殊支持:
- NewSQL 数据库(如 TiDB、CockroachDB)提供 AUTO_RANDOM 或分布式序列机制。

四、关键设计原则与建议
- 优先选择代理键: 95% 的场景推荐使用 自增ID(单机)或 雪花ID/UUID(分布式)作为主键。它们稳定、简单、解耦业务。
- 避免使用业务主键: 除非该业务属性 绝对稳定、简短且唯一性可保证(如身份证号,但需注意隐私和变更情况)。
- 禁止使用可能变更的字段: 如用户名、邮箱、公司名称等。
- 避免大字段做主键: 如 TEXT, BLOB,严重影响索引性能。
- 复合主键谨慎使用: 增加复杂度,影响关联表设计。仅在多对多关系表或强业务约束下使用。
- 显式定义主键: 即使有唯一索引,也应显式定义 PRIMARY KEY,优化器会优先使用。
- 主键就是聚簇索引(多数DBMS): 主键顺序影响物理存储(InnoDB)。有序ID(自增、雪花)插入性能远高于随机ID(UUID)。
- UUID 优化:
- 使用 UUIDv7(时间戳有序)代替 v4(完全随机)。
- 存储时转换为 BINARY(16) 减少空间(如 MySQL 用 UNHEX(REPLACE(UUID(), ‘-‘, ”)))。
五、示例选择指南
- 用户表 (user):id BIGINT AUTO_INCREMENT 或 id BIGINT(雪花ID)✅
- 绝对不要用 username 或 email 做主键!❌(可能变更,且较长)
- 订单表 (order):order_id VARCHAR(32)(包含日期+序列号的业务号,并额外加一个 id BIGINT AUTO_INCREMENT/雪花 作为主键)✅
- 业务号可做唯一索引,主键用代理键。
- 国家表 (country):country_code CHAR(2) PRIMARY KEY(ISO 3166-1 标准,稳定且短小)✅
- 用户-角色关联表 (user_role):(user_id, role_id) PRIMARY KEY(经典复合主键场景)✅
总结:最佳实践路径
- 默认选择: 单机/简单系统 → 自增整数 (AUTO_INCREMENT)。分布式系统 → 雪花算法 (Snowflake)。
- 特殊需求: 需要提前生成ID → UUIDv7。严格业务标识 → 业务键+代理键+唯一约束。
- 绝对底线:主键必须唯一、非空、稳定。无论选哪种方案,最终一定要在数据库层通过 PRIMARY KEY 约束来保证唯一性,这是最后的堡垒。
通过遵循这些原则,你就能设计出既高效又健壮的主键结构,为数据库的稳定性和扩展性打下坚实基础!
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/186935.html