返回

PostgreSQL 18 uuidv7()怎么用?时间排序UUID生成方法详解

2026-09-06 PostgreSQL UUID 2 0

在传统 PostgreSQL 应用中,gen_random_uuid() 生成的是 UUIDv4。它具有很好的随机性和全局唯一性,但由于 UUIDv4 的内容基本随机,将其作为 B-tree 主键大量插入时,索引页可能频繁发生随机写入。

PostgreSQL 18 原生加入了 uuidv7(),用于生成按时间排序的 UUID。官方文档显示,UUIDv7 将 Unix 时间戳、子毫秒时间信息以及随机数据组合起来,因此既保留 UUID 的全局唯一特征,又具有时间排序特性。

目前 PostgreSQL 18 已是当前稳定版本,2026年8月已发布 PostgreSQL 18.6。

uuidv7()怎么生成UUID?

最简单的方法直接执行:

SELECT uuidv7();

可能得到类似:019535d9-3df7-79fb-b466-fa907fa17f9e,返回值的数据类型就是 PostgreSQL 原生 uuid。

连续生成多个 UUID:

SELECT uuidv7()
FROM generate_series(1, 5);

与 UUIDv4 相比,UUIDv7 最重要的区别不是格式,而是UUID本身包含时间排序信息。PostgreSQL 官方也明确将其定义为 time-ordered UUID。

UUIDv7为什么可以按时间排序?

UUIDv7 的前半部分包含时间信息,因此生成时间越靠后的 UUID,通常其 UUID 字典序也越靠后。

例如:

SELECT uuidv7();
SELECT uuidv7();
SELECT uuidv7();

将这些 UUID 保存到数据库后:

SELECT id
FROM users
ORDER BY id;

可以获得与生成时间大致一致的排序结果。

需要注意的是,UUIDv7适合时间排序,但不能把它理解成严格递增的数据库序列。UUID 中仍然包含子毫秒和随机部分,因此在极短时间内生成多个 UUID 时,它们并不是简单的 1、2、3 这种连续增长值。

创建UUIDv7主键

实际项目中可以直接把 uuidv7() 设置为默认值:

CREATE TABLE users (
    id uuid PRIMARY KEY DEFAULT uuidv7(),
    username varchar(100) NOT NULL,
    created_at timestamptz NOT NULL DEFAULT now()
);

插入数据时无需手动生成 ID:

INSERT INTO users (username)
VALUES ('zhangsan');

INSERT INTO users (username)
VALUES ('lisi');

查询:

SELECT *
FROM users
ORDER BY id;

这样就可以使用 UUIDv7 作为业务表的主键。

PostgreSQL 的 uuid 类型本身就是128位标识符,可以存储不同版本的 UUID;PostgreSQL 18 原生支持 UUIDv4 和 UUIDv7。

如何从UUIDv7提取时间?

PostgreSQL 18 同时提供了 uuid_extract_timestamp():

SELECT uuid_extract_timestamp(
    '019535d9-3df7-79fb-b466-fa907fa17f9e'::uuid
);

返回值类型为:timestamp with time zone,也就是说,UUIDv7 不仅可以用于排序,还可以直接提取其中包含的时间信息。

还可以使用:

SELECT uuid_extract_version(
    '019535d9-3df7-79fb-b466-fa907fa17f9e'::uuid
);

结果为:7。

这对于调试和数据迁移都非常方便。官方文档明确支持从 UUIDv7 提取时间和 UUID 版本。

uuidv7()支持时间偏移

PostgreSQL 18 的 uuidv7() 还支持可选的 shift 参数:

SELECT uuidv7('1 day'::interval);

也可以:

SELECT uuidv7('-1 hour'::interval);

这个参数会对计算出来的时间戳进行偏移。不过,偏移后的时间必须处于 UUIDv7 的时间戳字段可表示范围内,否则 PostgreSQL 会报错。

一般业务开发中直接使用 uuidv7() 即可,不建议为了普通业务数据人为修改时间。

UUIDv7和UUIDv4怎么选?

UUIDv4 最大的特点是随机性强,实现简单,适合很多普通业务场景。UUIDv7则更适合需要全局唯一ID,同时又希望ID具有时间排序特性的应用,例如订单、日志、消息、事件、分布式业务数据等。

简单来说:

  • UUIDv4:随机 UUID
  • UUIDv7:时间排序 + 随机 UUID

如果项目使用 PostgreSQL 18,并且准备把 UUID 作为大表主键,UUIDv7 是值得优先考虑的新方案。PostgreSQL 官方也指出,时间排序的 UUID 有助于改善缓存策略。

总结

PostgreSQL 18 的 uuidv7() 最大价值,是让开发者不再需要依赖第三方扩展或应用层代码,就能原生生成时间排序UUID。

最常用的写法就是:

CREATE TABLE orders (
    id uuid PRIMARY KEY DEFAULT uuidv7(),
    amount numeric(10, 2),
    created_at timestamptz DEFAULT now()
);

对于新建的 PostgreSQL 18 项目,如果既需要 UUID 的分布式唯一性,又希望降低完全随机 UUID 对索引访问带来的不利影响,那么 UUIDv7 是一个非常值得考虑的主键生成方案。

顶部