PG 元老 Tom Lane 公司 crunchy data 发布了一篇 blog, 提到了 Postgres 18 令人兴奋的5个特性: AIO , UUID v7 , B-tree skip scan , 虚拟生成列 , oauth 2.0
以下内容来自该blog的翻译: https://www.crunchydata.com/blog/get-excited-about-postgres-18
Postgres 18 将在几周后发布!以下是一些最重要、最激动人心的功能的详细信息。
Postgres 18 正在添加异步 I/O。这意味着许多用例的读取速度更快。这也是 Postgres 未来一系列更大规模性能改进计划的一部分,其中一部分可能涉及多线程。期待在未来的版本中看到更多这方面的改进。
当数据尚未位于共享内存缓冲区中时,Postgres 会从磁盘读取数据,此时需要进行 I/O 操作来检索数据。同步 I/O 意味着每个磁盘请求都需要等待完成后才能继续执行其他操作。对于活动频繁的繁忙数据库来说,这可能会成为瓶颈。
Postgres 18 将引入异步 I/O,允许专用工作进程通过批量读取来优化空闲时间并提高系统吞吐量。此前,Postgres 依赖操作系统进行智能 I/O 处理,对于顺序扫描,需要操作系统或存储预读,而对于其他读取类型(例如位图索引扫描),则使用 Linux 的 posix_fadvise 等功能。Postgres 18 将这项工作转移到具有异步 I/O 的数据库中,将为数据库级别的批量操作提供一种更可预测且性能更佳的方法。此外,还将推出一个新的系统视图 pg_aios,用于提供有关异步 I/O 系统的数据。
Postgres 写入将继续同步 - 因为这是 ACID 合规性所需要的。
如果异步 I/O 看起来令人困惑,可以把它想象成在餐厅点餐。在同步模型中,你会下单,然后站在柜台前等待,直到食物准备好后才能做其他事情。在异步模型中,你下单后会收到蜂鸣器,然后你可以回到餐桌与朋友聊天,直到蜂鸣器响起,表示你的食物已经准备好了。
异步 I/O 将影响:
Postgres 默认会启用io_method = worker。默认情况下,有 3 个 worker,对于 CPU 核数更多的系统,可以进行 worker 调整。我目前还没有看到任何关于此问题的可靠建议,敬请期待我们团队的后续更新。
对于在 Linux 5.1+ 上运行的 Postgres,您可以利用 io_uring 系统调用并通过实际后端进行调用。
通过迁移到 v7,UUID 在此版本中得到了一些改进。
UUID 是随机生成的字符串,全局唯一,常用作主键。UUID 在现代应用程序中如此流行,原因如下:
它们是独一无二的:您可以使用从多个地方生成的密钥。(可以跨主机生成唯一ID, 对shared nothing的分布式数据库非常有用)
解耦:您的应用程序可以在将数据发送到数据库之前生成主键。
URL 模糊性:如果您的 URL 使用主键(例如 .../users/5),其他 URL 很容易被猜到(例如 .../users/6、.../users/7)。如果使用 UUID(例如 .../users/f47ac10b-58cc-4372-a567-0e02b2c3d479),则无法猜到其他 ID。
UUID v7 的新标准于 2024 年中期通过一系列标准更新发布。UUIDv4 是 UUID 的早期版本,原生支持 Postgres。但由于其相对随机性,大型表中的排序和索引存在性能问题,导致索引碎片化和局部性差。UUIDv7 有助于解决排序和索引问题。它仍然是随机的,但前 48 位(12 个字符)是时间戳,其余位是随机的;这使得大约在同一时间插入的数据具有更好的局部性,从而提高了可索引性。
时间戳部分是十六进制值(即压缩的十进制)。例如,以01896d6e4a5d6(hex) 开头的 UUID 表示2707238289622(decimal),即自 1970 年以来的毫秒数。

uuid v7 示例:
CREATE TABLE user_actions (
action_id UUID PRIMARY KEY DEFAULT uuidv7(),
user_id BIGINT NOT NULL,
action_description TEXT,
action_time TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_action_id ON user_actions (action_id);
Postgres 18 中的一些 multi columns B-tree 索引的性能有了显著提升。
在 Postgres 早期版本中,如果表中的列( status,date )上有索引,则该索引可用于匹配status和date字段的查询,或者仅查询status。
在 Postgres 17 及以下版本中,同一个索引不能用于回答仅针对date字段的查询;您必须对该列进行单独索引,否则如果该表没有合适的索引,数据库将采用顺序扫描 + 过滤方法。
在 Postgres 18 中,很多情况下,它可以自动将此多列索引用于仅涉及date字段的查询。这被称为跳跃扫描 (skip scan),允许系统“跳过”索引的某些部分。当status的唯一值个数很少时, 效果尤为明显. 此前可通过递归调用来模拟index skip scan, 例子:
当查询不使用条件中的前导列,并且省略的列基数较低(例如不同值的数量较少)时,此方法有效。优化的工作原理如下:
例如,如果我们有一个包含status和date列的销售表,我们可能有一个多列索引:
CREATE INDEX idx_status_date
ON sales (status, date);
示例查询可能有一个不包含status字段的 where 子句。
SELECT * FROM sales
WHERE date = '2025-01-01';
查询计划中没有任何内容告诉您这是一个跳过扫描,因此您最终会得到像这样的正常索引扫描,向您显示索引条件。
QUERY PLAN
-------------------------------------------------------------
Index Only Scan using idx_status_date on sales (cost=0.29..21.54 rows=4 width=8)
Index Cond: (date = '2025-01-01'::date)
(2 rows)
在 18 之前,将进行全表扫描,因为索引的前导列未包含在内,但通过跳过扫描,Postgres 可以使用相同的索引进行此索引扫描。
在 Postgres 18 中,由于 status 的基数较低且值较少,因此可以进行复合索引扫描。请注意,此优化仅适用于使用=运算符的查询,因此不适用于不等式或范围。
这一切都在 Postgres 优化器后台进行,因此您无需启用它。其理念是,它将有利于那些过滤器和条件经常变化且不一定与现有索引相关的分析用例。
查询优化器将根据表的统计信息和被跳过的列中的不同值的数量来决定是否值得使用跳过扫描。

PostgreSQL 18 引入了虚拟生成列。此前,生成列始终存储在磁盘上。这意味着,对于生成列,其值是在插入或更新时计算的,这会增加一些写入开销。
在 PostgreSQL 18 中,虚拟生成列现在是生成列的默认类型。如果定义生成列而没有明确指定 STORED,它将被创建为虚拟生成列。
CREATE TABLE user_profiles (
user_id SERIAL PRIMARY KEY,
settings JSONB,
username VARCHAR(100) GENERATED ALWAYS AS (settings ->> 'username') VIRTUAL
);
对于使用 JSON 数据的用户来说,这是一个很棒的更新,可以简化查询,并且可以根据需要随时进行数据更改或规范化。
请注意,虚拟生成列不可以创建index - 因为它们不存储在磁盘上。对于JSONB 的索引,请使用STORED生成列或表达式索引。
对于使用 Okta、Keycloak 和其他托管身份验证服务的用户来说,这是一个好消息,Postgres 现在已兼容 OAUTH 2.0。这在身份验证配置文件 (pg_hba.conf) 中指定。
Oauth 系统使用持有者令牌 (bearer token),客户端应用程序使用令牌而非密码来证明身份。令牌是一个不透明的字符串,其格式由授权服务器决定。此功能无需将密码存储在数据库中。它还允许由外部身份提供商管理更强大的安全措施,例如多因素身份验证 (MFA) 和单点登录 (SSO)。
Postgres 18 拥有来自 200 多位作者的 3,000 多个提交,数量惊人。虽然其中许多是功能,但 Postgres 查询优化器器和系统其他后台部分也有大量新增和优化。即使您不使用可选功能,它仍然能带来性能提升、错误修复和安全补丁,因此定期升级是一个不错的选择。
https://www.crunchydata.com/blog/postgres-data-flow
https://www.crunchydata.com/blog/get-excited-about-postgres-18
https://www.crunchydata.com/blog/understanding-postgres-iops
https://www.crunchydata.com/blog/indexing-jsonb-in-postgres
另外大家有没有注意到贡献者名单,华人越来越多了。其中两位来自杭州易景科技(HaloDB),满哥还是pg_arrow插件的作者和pg_duckdb的贡献者。谁说只有大厂的代码才能被社区接收?我不信!

