PostgreSQL中UUID v7作为主键


Postgres 有一个专门用于 UUID 的数据类型:uuid。UUID 是 128 位数据类型,因此存储单个值需要 16 个字节。

随机 UUID 不适合 B 树索引 - 并且 B 树索引是主键唯一可用的索引类型。
B 树索引最适合有序值 - 例如自动递增或按时间排序列。

UUID v7适合 B 树索引
UUID v7是产生按时间排序的值。这意味着每次生成新的 UUID v7 时,它的值都会更大。这使得它非常适合 B 树索引。

要在 Java 中使用 UUID v7,我们需要一个第三方库,例如java-uuid-generator:


<dependency>
  <groupId>com.fasterxml.uuid</groupId>
  <artifactId>java-uuid-generator</artifactId>
  <version>5.0.0</version>
</dependency>

然后我们可以使用以下命令生成 UUID v7:

Java 语言

UUID uuid = Generators.timeBasedEpochGenerator().generate();

从理论上来说这应该可以提高执行INSERT语句的性能。

  • 插入 UUID v7比插入常规 UUID v4快约 2 倍。

由于 UUID 长度 - 即使进行了所有这些优化,它也不是主键的最佳类型。

网友:
1、如果您选择 UUID 路线,请查看以下内容:
  • 确保您使用的列类型存储为 128 位。不要存储字母、数字和连字符。
  • 查看 UUID/GUID 的 COMB/顺序变体。它将 UTC 当前日期时间中的几位移入值中,因此它们是连续的,适合索引。

2、本文忽略了一个重要考虑因素,即 B-Tree 索引经常使用键压缩。当您的键较小且连续(大多数情况下)时,压缩效果非常好,索引更密集,因此速度更快。
由于 UUID 比严格需要的长得多,并且不太连续,它们包含更多必须在索引中跟踪的不可压缩的随机性,如果不是很连续,还需要更多的树重新平衡。

3、只需使用 ULID,问题已解决https://github.com/ulid/spec

4、使用整数主键供内部使用(连接等),并使用 uuid 索引供公众使用,或者仅使用 uuid 作为 PK。

5、如果您拥有大量数据行(数百万),那么如果表由 FK 引用,则 PK 的 UUID 对每个人都不利,因为索引的大小/哈希连接的性能会受到很大影响。在我看来,不变的 int PK 适合面向公众。
如果您没有很多数据行,那么自然键(如 SSN 或列的组合)对于面向公众来说非常友好。
 UUID 的唯一用途是支持用户界面,因为您可以在客户端为新行生成新的 UUID,这更方便。

6、UUID 的真正用途是集成。假设您有两家企业,其中一家收购了另一家,而您想要将记录合并在一起。很简单,所有东西在两个系统中都是唯一标识的,不会出现黑客迁移和下游服务中断的情况。或者假设您有一个离线工作的客户端,并且希望最终与主服务器同步,那么 UUID 就很有意义。