正在加载,请稍候…

UUID vs ULID:你应该使用哪种唯一标识符?

比较 UUID 和 ULID 格式在数据库主键中的应用,了解何时使用每种格式,并即时生成它们。

UUID vs ULID:你应该使用哪种唯一标识符?

什么是唯一标识符?

唯一标识符(UID)是字符串或数字,用于唯一标识数据库、分布式系统或通信协议中的记录。现代软件中最常见的两种格式是 UUID(通用唯一标识符)和 ULID(通用唯一字典序可排序标识符)。

选择错误的格式可能导致数据库性能下降、调试困难或兼容性问题。本指南将解释这两种格式,并帮助您决定使用哪一种。

UUID vs ULID:你应该使用哪种唯一标识符?插图

UUID:通用标准

UUID 在 RFC 4122 中定义,由 128 位组成,显示为 32 个十六进制字符,用连字符分隔:

550e8400-e29b-41d4-a716-446655440000

UUID 版本 4(最常见)对所有字段使用随机位。它大约有 122 位随机性——约 5.3 × 10³⁶ 个可能值。生成 10 亿个 UUID 时发生冲突的概率约为 10²⁰ 分之一。

UUID 版本 来源 用例
v1 MAC 地址 + 时间戳 遗留系统,暴露设备 MAC
v3 命名空间 + 名称的 MD5 哈希 从名称确定性生成
v4 随机 通用 ✅
v5 命名空间 + 名称的 SHA-1 哈希 从名称确定性生成
v7 Unix 时间戳 + 随机 可排序,现代 ✅

ULID:天生可排序

ULID 编码一个 48 位的毫秒时间戳,后跟 80 位随机性,显示为 26 个 Crockford Base32 字符:

01ARZ3NDEKTSV4RRFFQ69G5FAV
│──────────│──────────────│
  10 字符     16 字符
  (时间戳)    (随机)

由于时间戳是前缀,ULID 按字典序按时间顺序排序。在同一毫秒内创建的记录共享时间戳前缀,但随机后缀不同,从而保持唯一性。

UUID vs ULID:你应该使用哪种唯一标识符?插图

直接对比

特性 UUID v4 UUID v7 ULID
字符串长度 36 字符 36 字符 26 字符
可排序
URL 安全 需要编码 需要编码
包含时间戳
标准化 RFC 4122 RFC 9562 (2024) 社区规范
数据库索引性能 碎片化 良好 良好
可读性 中等

数据库性能:为什么可排序性很重要

在 B 树索引(PostgreSQL、MySQL)中,顺序插入比随机插入高效得多。UUID v4 的随机性导致索引碎片化:每个新行插入到索引树中的随机位置,导致频繁的页分裂和缓存未命中。

ULID 和 UUID v7 通过使用单调递增的值(大多数情况下)解决了这个问题,允许新记录追加到索引末尾附近,从而在高吞吐量系统中显著减少写入开销。

来自各种 PostgreSQL 实验的基准数据显示,在大型表(1 亿行以上)上,使用可排序 ID 的插入性能提高了 3–5 倍。

UUID vs ULID:你应该使用哪种唯一标识符?插图

何时使用 UUID v4

  • 最大兼容性——每个数据库、语言和框架都理解 UUID。
  • 无时间戳泄露——如果您不希望 ID 中嵌入创建时间。
  • 简单集成——在 SQL(PostgreSQL 13+ 中的 gen_random_uuid())、Node.js(crypto.randomUUID())、Python(uuid.uuid4())中可用。
  • 低到中等吞吐量——对于大多数每天记录量低于数百万的应用程序来说足够。

何时使用 ULID

  • 高写入数据库——事件溯源、日志、审计跟踪。
  • URL 安全 ID——没有连字符或特殊字符。
  • 调试——您可以从 ULID 本身提取创建时间。
  • 排序列表——用作分页游标,无需单独存储 created_at

何时使用 UUID v7

UUID v7(在 RFC 9562 中正式化,2024 年 4 月)提供了两全其美的方案:标准 UUID 格式,嵌入 Unix 时间戳以实现可排序性。它在数据库(PostgreSQL 17+)和库中得到越来越多的支持。对于新项目,UUID v7 通常是最佳选择。

实用代码示例

// UUID v4 — Node.js 内置
const { randomUUID } = require('crypto');
const id = randomUUID(); // "550e8400-e29b-41d4-a716-446655440000"

// ULID — npm 包
import { ulid } from 'ulid';
const id = ulid(); // "01ARZ3NDEKTSV4RRFFQ69G5FAV"
-- PostgreSQL UUID v4
SELECT gen_random_uuid();

-- PostgreSQL UUID v7 (pg 17+ 或 pgcrypto 扩展)
SELECT uuid_generate_v7();

→ 尝试 UUID 生成器ULID 生成器