丹尼尔·维里特:在纯SQL中实现UUID v7

💡 原文英文,约1900词,阅读约需7分钟。
📝

内容提要

2024年5月,IETF标准的UUID(通用唯一标识符)通过RFC 9562进行了更新,正式确认了UUID版本7。与以前的版本相比,这个版本在数据库索引中是更好的选择,因为它的值是按顺序生成的。尽管PostgreSQL还没有内置的生成UUID v7的函数,但是可以通过纯SQL实现这个功能。文章介绍了如何使用纯SQL实现UUID-v7的功能,并提供了相应的代码。同时,还讨论了UUID-v7生成值时可能出现的问题,并提供了解决方案。最后,文章还介绍了如何将UUID-v7用作分区键,并提供了相应的函数。

🔎

延伸解读

纯SQL实现的优势

文章指出,现有的UUID v7扩展通常用C或Rust等“不受信任的语言”编写,需要编译步骤和超级用户权限才能安装。而纯SQL实现则可以在任何环境中轻松创建,无需特殊权限,降低了使用门槛。这对于无法安装扩展或权限受限的环境尤其有用。

毫秒精度与排序问题

UUID v7的前48位是毫秒级Unix时间戳,但同一毫秒内生成的多个UUID,其剩余位是随机的,导致排序时顺序随机。文章通过示例展示,当每秒生成超过1000个UUID时,连续值可能不按生成顺序排列。这会影响索引效率,但文章也指出,在索引中这些值仍然彼此靠近。

亚毫秒精度解决方案

为了解决同一毫秒内UUID不排序的问题,文章介绍了利用rand_a字段的12位来存储亚毫秒精度。通过将毫秒后的小数部分映射到这12位,可以保证同一毫秒内生成的UUID也按顺序排列。文章提供了相应的SQL函数,并展示了排序结果。

分区键与时间戳提取

UUID v7包含时间戳,因此适合作为分区键。文章展示了如何用uuidv7_boundary函数生成分区边界,并给出了按月分区的示例。此外,还提供了从UUID v7中提取时间戳的函数,但只能提取毫秒部分,因为规范未承诺亚毫秒精度。

❓

Q&A

UUID v7的主要特点是什么?

UUID v7的主要特点是其值按顺序生成,适合用于数据库索引。

如何在PostgreSQL中生成UUID v7?

可以通过纯SQL实现UUID v7的功能,使用特定的SQL函数来生成。

UUID v7生成时可能遇到哪些问题?

生成UUID v7时可能遇到毫秒精度不足的问题,导致相邻UUID不排序。

如何解决UUID v7生成中的排序问题?

可以通过忽略问题、使用计数器或采用亚毫秒精度来解决排序问题。

UUID v7可以作为分区键使用吗?

是的,UUID v7可以用作分区键,并可以生成分区边界。

如何从UUID v7中提取时间戳?

可以使用特定的SQL函数提取UUID v7中的时间戳,返回毫秒部分。

🏷️

标签

➡️

继续阅读