Skip to content
自增还是UUID,数据库主键的类型该如何选择?

自增还是UUID,数据库主键的类型该如何选择?

在设计新的SQL数据库模式时,一个关键的决策是选择主键的类型。最常见的两种选择是UUID和自增整数(在某些数据库中也称为Serial)。这个选择会对数据库的功能和性能产生重大影响,并且一旦数据库投入使用,通常很难更改。

自增整数/Serial

自增整数/Serial得到了主要数据库引擎的广泛支持。例如,MySQL使用AUTO_INCREMENT,PostgreSQL有SERIAL,SQL Server使用IDENTITY,SQLite使用AUTOINCREMENT。

优点

  1. 可读性强:与UUID相比,它更具可读性,尤其是在对外暴露时。例如,像issue - 123这样的问题ID比issue - b1e92c3b - a44a - 4856 - 9fe3 - 925444ac4c23这样的UUID更容易理解。
  2. 占用空间少:UUID总是占用16字节,而以长整型存储的自增整数占用8字节。在列数较少的表中,UUID作为主键所占用的额外空间会更加明显。

缺点

  1. 不适用于分布式系统:在分布式系统中,不同的主机可能会生成相同的数字,这使得它无法用作唯一标识符。
  2. 不能即时生成:它需要查询数据库以获取下一个可用的主键。在分布式系统中,这通常意味着要引入一个单独的服务来生成顺序数字,而这个服务可能会成为单点故障(SPOF)。
  3. 业务数据可能暴露:最新的ID可能代表库存数量,攻击者可能会扫描整数范围以寻找数据泄漏。尽管通过正确实施访问控制列表(ACL)应该可以防止这种情况,但这仍然是一个风险。

UUID

原始的UUID标准包括5种格式,其中UUIDv1(时间戳)和UUIDv4(随机)是最常用的。

优点

  1. 全球唯一:它极不可能出现重复,这对于在不同环境中需要唯一标识的系统非常有用。例如,在系统之间迁移数据时,冲突的可能性仅仅是理论上的。
  2. 无状态且可即时生成:它可以在不依赖任何外部状态的情况下生成,这对于各种应用程序都很方便。
  3. 具有安全性:恶意用户很难猜出ID,提供了一定程度的安全性。然而,根据安全团队的要求,公共可访问的UUID路径可能不符合安全标准。
  4. UUIDv1和时间戳:UUIDv1存储时间戳信息,在某些情况下可能有用。

缺点

  1. 可读性差:UUID是复杂的字符和数字字符串,人类很难阅读和理解。
  2. 不能按创建时间自然排序:尽管UUIDv1包含时间戳信息,但它的编码方式使得按创建时间排序很困难。它采用小端序格式,最低有效时间排在前面,这使得按创建时间排序变得复杂。
  3. 对某些数据库性能有影响:在像MySQL和Oracle这样使用聚集主键的数据库中,使用UUIDv1或UUIDv4作为主键会影响插入性能。这是因为需要重新排列行,以便将新插入的行放置在聚集索引中的正确位置。相比之下,使用堆而不是聚集主键的PostgreSQL则不受此影响。

UUIDv7 - 一种折衷方案

UUIDv7是一种新的格式,IETF在2021年4月的一份草案中提出,并于2024年5月最终批准。

布局和特点

UUIDv7的布局如下:

## uuid7布局
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           unix_ts_ms                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          unix_ts_ms           |  ver  |       rand_a          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var|                        rand_b                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            rand_b                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

与UUIDv1的最大区别是,前48位(unix_ts_ms)存储以大端序无符号数表示的Unix纪元时间戳(以毫秒为单位)。这使得稍后生成的UUID具有更高的值,便于按创建时间进行排序和查询。

由于UUIDv7是按时间顺序的,在数据库中插入新记录时,它减少了对随机I/O操作的需求,从而提高了性能并使索引更有效。

与其他键类型的比较

  1. 可排序:与UUIDv1不同,它是可排序的。
  2. 时间精度:它具有毫秒级的时间精度,在某种意义上与UUIDv1的纳秒精度类似,都提供了一种基于时间对记录进行排序的方法。
  3. 全球唯一:与其他UUID版本一样,它是全球唯一的。
  4. 无状态:与其他UUID版本一样,它是无状态的。
  5. 可读性:与其他UUID版本一样,它不如整数可读。

预期采用情况

由于它相对于先前的UUID版本具有优势,并能够解决一些关键限制,预计行业将逐渐将UUIDv7作为大多数用例的主键,取代定制解决方案。

结论

在UUID和自增整数/Serial之间选择作为主键取决于多种因素,如应用程序的性质、所使用的数据库系统以及对唯一性、可读性和性能的要求。自增整数/Serial具有可读性强和占用空间少的优点,但在分布式系统和数据安全方面存在局限性。UUID提供全球唯一性和一定的安全性,但可读性较差,在某些数据库中可能存在性能问题。UUIDv7似乎是一个有前途的折衷方案,提供了两者的一些优点,同时解决了一些关键缺点。随着行业的发展,预计UUIDv7作为主键选项将越来越受欢迎。

开始体验 Chat2DB Pro

如果你正在寻找一款强大、基于 AI 的数据库管理工具,快来试试 Chat2DB 吧!无论你是数据库管理员、开发者还是数据分析师,Chat2DB 都能通过 AI 的强大功能简化你的工作。

👉现在享受 Chat2DB Pro 30 天免费试用 (opens in a new tab),即刻体验所有高级功能。