要点:UUID v4 是随机唯一 ID 的安全默认;当你还需要按创建时间排序的 ID 时,ULID 更合适;需要简短、适合放进 URL 的 ID 时,NanoID 最理想。三者都无需系统间协调,但在长度、可排序性和数据库索引行为上各有取舍。本文说明它们各是什么、何时使用。
唯一标识符让相互独立的系统无需向中央服务器询问“下一个编号是多少”即可创建记录。这种独立性正是关键:两个服务,或两台离线设备,可以各自生成 ID,并确信这些值不会发生碰撞。

UUID 到底是什么
UUID 是一个 128 位的值,通常写成 36 个字符——32 个十六进制数字加 4 个连字符,例如 550e8400-e29b-41d4-a716-446655440000。你几乎总会想用的版本是 UUID v4,它用随机性填充其中 122 位,可产生约 5.3 × 10³⁶ 个可能值。因此碰撞无需专门防范:你要生成约 10^18 个 UUID,碰撞概率才会达到 50%。
“可忽略”不等于“不可能”,但在实践中 v4 无需任何中央协调即可提供唯一性。
UUID v4 与 v1
UUID v1 由时间戳加生成机器的网络(MAC)地址构成。这让 v1 大致按时间有序,但可能泄露 ID 的创建地点与时间——有时是隐私隐患。UUID v4 舍弃这些,改用纯随机:没有顺序、没有内嵌元数据、没有可泄露之物。对多数应用,v4 是正确默认;只有当你确实需要其时间成分时,v1 才值得。
ULID:天生可排序
ULID 同样是 128 位,但用 26 个 Crockford base32 字符编码,而非带连字符的十六进制。前 48 位是毫秒级时间戳,其余 80 位为随机。由于时间戳在前,ULID 会按创建顺序在字典序上排序:对字符串排序即无需额外处理即可得到时间顺序。这一点很实用:让“最新优先”的查询更省成本,并使数据库插入保持有序而非分散。
NanoID:短小且适合 URL
NanoID 默认使用 21 个来自 URL 安全字符集的字符,因此无需百分号编码即可放入链接。长度可配置,让你在体积与抗碰撞之间权衡:更短的 ID 更整洁但随机性更少,因此面向公开或高并发的标识符应保持较长。NanoID 适合分享链接、简短的公开 ID,以及任何 36 字符 UUID 在 URL 中显得笨重的场景。
数据库主键该选哪个?
这里的选择会带来实实在在的性能后果。UUID v4 作主键完全可行,但其随机性会让新行插入到 B-tree 索引的随机位置,随表增长造成碎片与更多页分裂。按时间有序的标识符——ULID,或更新的 UUID v7——大致按递增顺序插入,使索引紧凑、写入局部化。为大型、写密集的表选键时,优先按时间有序的 ID;小表则很少有差别。
需要避免的常见错误
- 本想要不可猜测的 ID,却把连续整数 ID 公开——这是随机 ID 的活,而非自增主键的。
- 把随机 UUID v4 用作超大表的聚簇键,然后纳闷为何插入变慢。
- 为“省空间”截断 UUID——你丢掉了保证唯一性的随机性。
- 为高并发标识符把 NanoID 截得过短,抬高碰撞风险。
让 ID 匹配用途:用UUID 生成器创建 v4、v1、ULID 或 NanoID,通用唯一性选 v4,需要顺序时选 ULID,ID 要放进 URL 时选 NanoID。