该用 v4 还是 v7
v4 的 122 位全是随机数。光看值,看不出它是什么时候、在哪里生成的。公开网址里的标识、邀请链接这类需要藏住生成顺序的地方,用它正合适。
v7 把前 48 位放成毫秒时间戳,其余填随机数,所以直接按字符串排序就是按生成时间排序。数据库主键、日志标识、事件 ID 这些吃时间顺序的地方用它。代价是生成时间从值里就能读出来,如果这件事本身不该外泄,就换回 v4。
NIL 是全为 0 的特殊值,用作占位符,填进那些不接受 NULL 又暂时没有值的列。
拿来做数据库主键
用 UUID 代替自增整数,多台服务器不用互相商量就能各自生成主键,而且 ID 出现在网址里也没法据此猜到相邻的行。
麻烦在 v4 的随机性。B-tree 索引最喜欢新键追加在末尾,而 v4 每次都插进索引中间的随机位置,页面于是不停分裂。表越大写入越慢,索引也越胖。v7 的值随时间递增,新键总是落在末尾,正好躲开这个问题。新建的表用 v7 当默认选择比较稳妥。
MySQL 存成 BINARY(16),PostgreSQL 用 uuid 类型。存成 36 个字符的字符串,每行多花 20 个字节,比较也更慢。
去掉连字符的写法
连字符只是规范定的显示方式,不属于值本身。文件名、优惠码和一些 API 的返回里用的是连成一串的 32 个字符。大写同理,只是呈现差别;比较两个 UUID 时,先统一转成小写更保险。
一次生成多个时
这个工具一次生成多个 v7 时会保持生成顺序。同一毫秒内生成的值时间戳相同,本来会打乱顺序,所以随机部分中的一段被拿来当计数器。把列表整段复制出去,排序也不会乱。