外观
主键一般用自增 ID 还是 UUID
在数据库设计中,UUID
和自增ID
是常用的两种主键生成方式,各自有其优缺点。
自增 ID
优点
- 性能优势:在
InnoDB
存储引擎中,自增ID
作为聚簇索引,数据按顺序存放,插入时只需不断向后排列,能提高插入性能,且对基于主键的查询、范围查询和排序操作都很友好,可快速定位数据。 - 空间节省:通常为整数类型,占用空间比
UUID
小。 - 操作简单:由数据库自动管理,开发人员无需手动生成和维护,减少了开发工作量和出错概率。
缺点
- 分布式问题:在分布式系统或分库分表场景中,各节点自增
ID
可能冲突,需额外逻辑保证全局唯一性。 - 数据迁移与集成困难:数据库合并或迁移时,自增主键可能导致冲突,需重新调整序列或处理重复问题。
- 安全问题:具有一定规律,容易被非法获取数据,泄露数据库的记录数量、增长速度等信息。
- 热点问题:高并发写入时,自增值可能成为写入 “热点”,所有写操作集中在一个位置,影响写入性能。
适用场景
- 单机版项目:如大型企业内部的单机数据库系统,对性能和存储空间要求高,自增
ID
能发挥性能和空间优势。 - 对数据顺序有要求:如日志表、订单表等,需要按照插入顺序进行查询和处理,自增
ID
可保证数据的有序性。 - 简单的业务系统:业务逻辑简单,数据交互和集成需求少,使用自增
ID
可简化开发和维护过程。
UUID
优点
- 全局唯一性:
UUID
是128
位的唯一标识符,生成的值在全球范围内是唯一的,非常适合分布式系统。 - 灵活性:生成不依赖数据库,可在应用层完成,在分布式系统中能方便地生成新主键,无需与数据库频繁交互。
- 安全性高:随机性和复杂性使其难以被猜测或伪造,一定程度上提高了系统的安全性。
- 跨服务器数据合并方便:在跨服务器数据合并时,无需担心主键冲突问题,可以直接进行合并操作。
缺点
- 存储开销大:是
128
位字符串,占用存储空间比自增ID
大,会增加磁盘I/O
和内存开销。 - 查询性能问题:在
InnoDB
等存储引擎中,UUID
的无序性可能导致B +
树索引碎片化,影响查询性能,范围查询效率也较低。 - 可读性差:由
32
个十六进制数字组成,不直观,可读性差,排查问题和开发调试时不太方便。
适用场景
- 分布式系统:如微服务架构、大规模分布式电商系统等,数据可能存储在多个节点或不同数据库中,
UUID
能保证全局唯一性。 - 对数据安全性要求高:如金融系统、用户认证系统等,
UUID
的不可预测性和难伪造性可提高数据安全性。 - 数据整合与交换频繁:系统间数据交互多,需要频繁进行数据导入、导出和合并操作,
UUID
可避免主键冲突。
扩展:
为了克服UUID
的无序性问题,可以使用有序UUID
。MySQL 8.0
提供了uuid_to_bin
函数,可以将UUID
转换为有序UUID
,从而提高插入性能。有序UUID
既保证了全局唯一性,又具备单调递增的特性,适合作为主键。也可以使用雪花 ID(Snowflake ID)
来作为主键ID
,顾名思义:世界上没有两片相同的雪花。雪花算法是一种在分布式系统中用于生成唯一 ID
的算法,在分布式系统中比自增ID
和UUID
更加具有优势。雪花 ID
是一个 64
位的二进制数字,使用时间戳、工作机器 ID
和序列号等因素来生成唯一的标识符,具体组成如下:
符号位(1 位):始终为 0
,用于标识正数。
时间戳部分(41 位):记录 ID
生成的时间戳,精确到毫秒级。可以表示约 69
年的时间范围,从某个固定的起始时间开始计算。
工作机器 ID 部分(10 位):用于标识生成 ID 的工作机器或节点。这部分可以进一步划分为机房 ID
和机器 ID
,通常机房 ID
占 5
位,机器 ID
占 5
位,可以支持 1024
个不同的工作机器或节点。
序列号部分(12 位):同一毫秒内,在同一台工作机器上生成的 ID
的序列号,用来区分同一毫秒内产生的不同 ID
。12
位的序列号可以在同一毫秒内支持 4096
个不同的 ID。
对比:
特性 | 雪花ID | 自增ID | UUID |
---|---|---|---|
唯一性 | 分布式环境下全局唯一 | 单机环境下唯一 | 全球唯一,但概率极小重复 |
性能 | 高,内存生成,支持高并发 | 高,但不支持分布式 | 低,字符串操作性能差 |
存储空间 | 64 位整数,占用空间小 | 通常为32 位或64 位整数 | 128 位(十六进制)36 字符,占用空间大 |
索引效率 | 高(递增ID) | 高(递增ID) | 低(无序字符串) |
适用场景 | 分布式系统、高并发环境 | 单机系统、高效查询场景 | 分布式系统、需要保密的场景 |