Utilo

UUID v4 vs UUID v7 vs ULID:你应该使用哪个唯一ID?

对于数据库密钥,API和分布式系统,与性能,隐私和格式权衡进行随机 UUID v4,时间顺序 UUID v7 和 ULID 的比较。

· 5 分钟阅读

自动增加的整数几十年来一直是默认的初级密钥。它们是紧且快速的,但它们需要一个中央数据库来分配数字,泄露你有多少记录,。全球独一无二的识别符解决了这些问题:任何服务器,移动应用程序或离线客户端都可以创建一个永远不会碰撞的ID。问题在于是哪种。本指南比较了2026年最流行的三个选项:UUID版本 4,UUID版本 7 和 ULID。

一个快速的更新 UUID

UUID (通用唯一标识符) 是一个128位的值,通常用32个十六进制数字写成五组:

550e8400-e29b-41d4-a716-446655440000

目前的标准RFC 9562 (于2024年发布,取代RFC 4122),定义了几个版本。一些位符号编码版本和变体;其余取决于版本。第三组始于版本号,所以你可以一眼看出v4和v7。

UUID v4:完全随机

一个版本4 UUID 包含 122 个随机位加上 6 个版本和变体的固定位。

优势

  • 每种语言和数据库都有内置的函数,例如JavaScript中的crypto.randomUUID()或PostgreSQL中的gen_random_uuid()。
  • 没有时间,没有机器标识符,没有序列。
  • 碰撞的可能性是微不足道的。需要生成约2.7 × 10^18的ID,

弱点

  • 随机顺序会损害数据库索引。在PostgreSQL,MySQL和SQL服务器中使用的B树索引,在新密钥以不断增加的顺序到达时表现最好。随机键会在索引中出现,导致页面分裂,缓存位置不好,。在大型表格中,插入吞吐量可能会显著下降,索引会比必要的更大。
  • 不能按创建时间进行排序,所以需要一个单独的 created_at 列来进行时间查询。

UUID v7:时间顺序

版本7将 48 位 Unix 时间放在前面的毫秒,其次是 74 位随机性 (一些实现将其部分作为在同一毫秒内排序的计时器)。

01928c3e-5b7a-7c4d-9f3e-2a1b4c5d6e7f
└─timestamp─┘ └version 7

优势

  • 新的ID大致增加,所以插入添加到索引的末尾像自动增量键。这使得索引紧,写作快。
  • 按创建时间按ID排序排序,这使得基于光标的排列简单:WHERE id > :last_id ORDER BY id LIMIT 50。
  • 它仍然是一个标准 UUID:它适合已经接受 UUID 的原生 uuid 列,ORM 和 API。
  • 你可以从ID中提取创建时间进行调试。

弱点

  • 创建时间是任何看到ID的人都能看到的。对于大多数记录来说,这是无害的;对于一些用户来说,例如隐私敏感产品中的用户帐户,它可能会显示某人何时注册。
  • 需要一个相当精确的钟。大量的时钟跳向后可以产生比现有的ID更早排序的ID;好的图书馆使用单调计数器来处理这一问题。
  • 本源生成函数是较新的。PostgreSQL 18添加了 uuidv7();在旧版本中,生成应用程序代码。

ULID:可分类和紧的文本

ULID (普遍独特的词典解析识别器) 之前 UUID v7 使用相同的想法:48 位毫秒时间,其次是 80 个随机位。区别在于文本形式:Crockford Base32的26个字符。

01J9Z3K8M2Q7X4V5B6N8P0R2T4

优势

  • 短于36个字符的 UUID 字符串和 URL 安全。
  • 字母大写不敏感,不含含糊的字母 (I,L,O,U),因此更容易大声阅读或打字。
  • 词典学字符串排序等于时间排序,这有助于存储ID作为文本的系统,例如关键值存储或日志文件名。

弱点

  • 它不是 UUID,因此它不适合没有转换的原生 UUID 列类型 (尽管其 128 位可以存储在一个中)。
  • 一个社区规范而不是IETF标准,图书馆之间的行为略有不同。
  • 像V7一样,它暴露了创造时间。

一对一的比较

财产 其他 无线路标识号 标签:
尺寸 128位 128位 128位
文本长度 36 36 26
时间排序 没有 是的 是的
泄露创建时间 没有 是的 (ms) 是的 (ms)
标准 其他类型 其他类型 欧盟规范
本机DB类型 uuid uuid 通常是文本或二进制
适合索引的插件 穷人 很好 很好

储存技巧

无论你选择什么,存储ID为16字节,而不是文本。一个36个字符串占用空间的两倍以上,。PostgreSQL具有原生 uuid 类型;MySQL 用户可以使用 BINARY(16) 与 UUID_TO_BIN(uuid, 1),第二个参数重新排序 v1 时间对于 v7 使用默认排序,因为它已经排序时间。

在APIs中以其正规文本形式展示ID。客户应该把它们视为不透明的字符串,

安全考虑

这些身份证都不是秘密。不要把它们当作密码重置令牌或会话标识符,。一个v4 UUID有足够的随机性无法测量,但v7和ULID具有可预测的时间前,可减少有效的。对于秘密,使用加密生成器生成至少128个随机位,并将它们视为密码,理想情况下只存储一个哈希。

另外还要考虑列举。顺序整数可以让任何人猜到/orders/1001,/orders/1002。随机或时间顺序的ID使得这不切实际,但它们不能取代每一个请求的授权检查。

你应该选择哪一种?

  • 新系统中的数据库初级密钥: UUID v7。您可以获得分布式生成和良好的索引性能,
  • 公共标识符,创建时间必须保持私密: UUID v4,或 v7 内键结合单独的随机公共标识符。
  • 基于文本的存储,文件名或ID,人们可以输入: ULID,其较短,小写不敏感的形式。
  • **现有系统在v4上出现性能问题:**对于新表,考虑v7;在一个列中混合版本在技术上很好,因为两者都是有效的 UUID。

生成标识符

对于快速任务种子数据,测试装置,手动插入基于浏览器的UUID生成器可以使用crypto.getRandomValues同时生成高达1,000个v4,v7或ULID值。在应用程序代码中,使用您语言的标准库或维护良好的包,并尽可能接近创建记录的ID。

总结

虽然 UUID v4 是随机和私有,。UUID v7 添加了一个时间前,使插入快速,ID 可分类,同时保持标准 UUID。ULID提供了相同的排序方式,。对于大多数新应用程序来说,UUID v7 是最佳默认;当定时必须隐藏时,达到v4,当人类或基于文本的系统处理ID时,ULID。

本页内容由英文自动翻译而来,如发现错误,欢迎告诉我们。

相关指南