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。
本页内容由英文自动翻译而来,如发现错误,欢迎告诉我们。