
什么是唯一标识符?
唯一标识符(UID)是字符串或数字,用于唯一标识数据库、分布式系统或通信协议中的记录。现代软件中最常见的两种格式是 UUID(通用唯一标识符)和 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 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 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();