大家好,我是农村程序员,独立开发者,行业观察员,前端之虎陈随易。
- 个人网站 1️⃣:chensuiyi.me
- 个人网站 2️⃣:me.yicode.tech
如果本文能给你提供启发或帮助,欢迎动动小手指,一键三连(点赞、评论、转发),给我一些支持和鼓励,谢谢。
PostgreSQL 18.0 更新速览:AIO、uuidv7、OAuth、pg_stat_io(以及升级要注意的坑)
PostgreSQL 18.0(Release date: 2025-09-25)这版,我看完 release notes 之后的感受是:
这不是"修修补补",这是"从内核到体验"的一轮升级。
官方 release notes 在这里(建议收藏):
(说明:本文以 PostgreSQL 18.0 release notes + v18 文档为准;18.x 小版本一般以 bugfix 为主,不影响本文对"大特性"的理解。)
下面我挑一些我觉得 重要 / 有趣 / 真能用起来 的点,尽量用人话讲清楚。
1)AIO:数据库终于开始"认真并发读写"
PostgreSQL 18 引入了 异步 I/O(AIO)子系统,会影响(并且可能加速)这些典型场景:
- 顺序扫描(sequential scans)
- bitmap heap scans
- VACUUM / ANALYZE
- 以及一堆"会读很多数据"的操作
官方描述里一个很关键的点是:后端可以一次性排队多个 read 请求,让顺序扫描、vacuum 等更高效。
怎么开?
核心开关是 io_method(需要重启生效):
worker:用 I/O worker 进程执行异步 I/O(默认)io_uring:用 Linuxio_uring(需要编译时启用 liburing)sync:把"可异步的 I/O"同步执行(等于先别折腾)
配套还有:
io_workers:worker 模式下 I/O worker 数量io_combine_limit/io_max_combine_limit:控制合并 I/O 的最大 size
另外,release notes 里还提到:AIO 的引入,也让一些系统在没有 fadvise() 支持时,effective_io_concurrency / maintenance_io_concurrency 也能设置为 > 0。
怎么观测?
PG18 新增系统视图 pg_aios,能看到正在使用的 AIO handle(偏开发/调优向,但很好用):
以及等待事件里也能看到 AIO 相关项(比如 io_uring submit/execution)。
如果你是 DBA/运维同学,我的建议是:
- 先在压测环境开
io_method=worker看收益 - 结合
pg_stat_io(后面会讲)观察读写 bytes、fsync 等指标 - 再考虑是否值得为
io_uring做编译与内核/文件系统/权限层面的投入
2)pg_upgrade 不再"升级后冷启动":开始保留优化器统计信息
以前大版本升级常见一个尴尬期:
你升级成功了,但统计信息没了,执行计划像"刚装系统一样",性能波动一阵子。
PostgreSQL 18 的 pg_upgrade 默认会转移大部分 optimizer statistics (可以用 --no-statistics 关闭)。
官方文档也说得很清楚:
- 并不是所有统计都能转(比如
CREATE STATISTICS这类 extended statistics 不一定保留) - 升级后依然建议补一轮统计生成
pg_upgrade 文档对应章节:
它甚至给出了建议流程:先用 缺失统计补齐模式 快速补缺,再全量 analyze 保证齐全。
这里我把命令写得更精确一点(避免误用):
-
先跑:
vacuumdb --all --analyze-in-stages --missing-stats-only- 注意:
--missing-stats-only只能 和--analyze-only/--analyze-in-stages搭配使用(它的目的就是"只补缺失的统计信息")。
- 注意:
-
再跑:
vacuumdb --all --analyze-only
我个人非常喜欢这一点:属于"升级体验"级别的优化。
3)Skip Scan:多列 B-tree 索引终于没那么"左前缀死板"了
PostgreSQL 18 加了 B-tree skip scan。这句话的实际含义是:
多列 B-tree 索引,在"缺少前导列等值条件"的情况下,也有机会被用上。
多列索引的经典规则是:对最左列(leading column)约束越强越有用;如果你只约束了后面的列,往往扫很大一段索引甚至干脆不用。
skip scan 的做法是:在某些情况下,PG 会在内部生成"动态等值约束",通过多次 index search 来"跳过"不可能命中的索引叶子页,从而减少要读的索引范围。
官方在"多列索引"章节里直接解释了 skip scan,并给了例子:
- 索引
(x, y),查询WHERE y = 7700,有可能用 skip scan - 但通常只有在
x的 distinct 值很少、能跳过大量 leaf page 时才划算
文档在这里(强烈推荐读一遍):
我对这个特性的评价:
- 对写业务的同学:不用你改 SQL,就可能变快(当然要看数据分布)
- 对做索引设计的同学:以前"不敢建"的多列索引,现在可能更值钱
4)uuidv7():时间有序 UUID,写入与索引更友好
PG18 内置了 uuidv7():生成 timestamp-ordered 的 UUID(版本 7)。
官方函数文档里写得很明确:
uuidv7()使用 UNIX timestamp(毫秒精度)+ 次毫秒时间 + random- 可选参数
shift interval可以让生成时间偏移
对应文档:
顺带还有两个很实用的"解剖函数":
uuid_extract_timestamp(uuid):从 v1/v7 UUID 里提取时间戳uuid_extract_version(uuid):提取版本号
为什么我说它"真能用起来"?因为很多系统以前用 UUIDv4(完全随机),在 B-tree 上写入会更像"到处插",页分裂/缓存局部性都比较尴尬。
uuidv7 这种"时间大致有序"的特性,在一些高写入场景(尤其主键就是 UUID 的表)会更舒服。
5)Generated Columns:默认变成 VIRTUAL(省空间,但也有坑)
PostgreSQL 18 增强了 generated columns:
- 支持 VIRTUAL generated columns(读取时计算,不占存储)
- 并且 VIRTUAL 现在是默认(在 PostgreSQL 18 之前,generated column 只有 STORED)
语法仍然是:
GENERATED ALWAYS AS (expr) [ STORED | VIRTUAL ]
官方文档在 CREATE TABLE 参数里写得很细:
- VIRTUAL:读取时算,不占磁盘
- STORED:写入时算,落盘
- 生成表达式必须 immutable
并且还有一个非常重要的限制(很多人会踩):
虚拟 generated column 不能使用用户自定义类型,且表达式不能引用用户自定义函数/类型(只能用内置函数/类型)。
文档:
我的建议是:
- 你要的是"存储空间/写入开销更低",或者表达式经常改:选 VIRTUAL(默认就是)
- 你要的是"读性能稳定"、表达式复杂且允许用自定义函数:用 STORED
6)RETURNING 终于支持 old/new:审计、diff、业务回写都舒服了
PG18 给 DML 的 RETURNING 加了 old / new:
INSERT/UPDATE/DELETE/MERGE都能显式取 old/new- 典型用法是:一次 SQL 就把"变更前后"带回来,不用再查一遍
官方文档例子(我直接抄核心模式):
sql
UPDATE products
SET price = price * 1.10
WHERE price <= 99.99
RETURNING
name,
old.price AS old_price,
new.price AS new_price,
new.price - old.price AS price_change;
文档:
另外一个小细节:
INSERT通常 old 为 NULLDELETE通常 new 为 NULL
但在 INSERT ... ON CONFLICT DO UPDATE 这种场景,old/new 都可能有意义。
7)OAuth:PostgreSQL 也开始对接企业"票据体系"
PostgreSQL 18 新增 OAuth 认证方式:
pg_hba.conf里会出现oauth认证方法- libpq(psql/应用)侧有对应 OAuth 选项
- 需要编译时启用 libcurl(release notes 里明确提到
--with-libcurl)
OAuth 文档里有几个点值得高亮:
- 服务器端要配置
issuer、scope等 issuer与 discovery document 的 issuer identifier 必须严格匹配(大小写/格式都不允许差一点点)validator/oauth_validator_libraries负责 token 校验(不同部署会很不一样)
文档:
我对 OAuth 的理解:
- 对企业内网、数据平台、统一登录场景,这是"终于等到官方支持"的那种特性
- 但这块落地成本也不低,尤其是 validator 的实现与安全边界要设计清楚
8)可观测性:pg_stat_io 更细、还能看每个 backend 的 I/O/WAL
这一块是我觉得 PG18 最"运营友好"的升级之一。
8.1 pg_stat_io 终于开始按 bytes 统计
release notes 明确提到:
pg_stat_io增加了read_bytes/write_bytes/extend_bytes- 以前那个永远等于
BLCKSZ的op_bytes被移除了 - 还增加了 WAL I/O 行(包括 wal receiver 等)
对应文档里对 pg_stat_io 的定义也很清晰(backend_type / object / context 三维组合):
你可以先从这种查询开始:
sql
SELECT backend_type, object, context,
reads, read_bytes,
writes, write_bytes,
fsyncs, fsync_time
FROM pg_stat_io
ORDER BY read_bytes DESC NULLS LAST;
8.2 每个 backend 的 I/O 统计:定位"谁在折腾磁盘"
PG18 增加了:
pg_stat_get_backend_io(pid):拿到某个 pid 的 I/O 统计(字段同 pg_stat_io)
文档:
这对排查"到底是谁在大量 bulkread/bulkwrite/vacuum I/O"很有帮助。
9)升级前必看的兼容性变化(别踩坑)
PG18 有一些变化,我建议升级前就拉一张 checklist(这里挑几个最容易影响到人的):
9.1 initdb 默认开启 data checksums
PG18 改成:initdb 默认启用数据校验和(data checksums)。
- 可以用
initdb --no-data-checksums关掉 pg_upgrade要求新旧集群 checksum 设置一致,所以这个选项对升级"旧集群没开 checksum"的场景很关键
(这一条在 release notes 的 incompatibilities 里写得很明确。)
9.2 MD5 password 认证被标记为弃用
MD5 password authentication 进入弃用状态:
- 未来大版本会移除
CREATE ROLE/ALTER ROLE设置 MD5 password 会发 deprecation warning- 可通过
md5_password_warnings=off关闭警告(但不建议掩耳盗铃,还是尽快迁移到更安全的方式,比如 SCRAM)
9.3 VACUUM / ANALYZE 默认会处理继承子表
PG18 改了行为:对父表执行 VACUUM/ANALYZE 时,会处理 inheritance children(对分区表也类似:默认会处理子分区)。
- 以前那种"只处理父表"的行为,现在要用
ONLY选项显式表达
9.4 COPY FROM CSV 不再把 \. 当 EOF
PG18 不再在 CSV 模式下把 \. 当作 EOF 标记。
- psql 仍然会在从 STDIN 读 CSV 时把
\.当 EOF - 旧版本 psql 连到 PG18 服务器,使用
\copy可能会出问题 - 并且这版还要求
\.必须独占一行
这类变化看似边角,但线上一旦命中就很致命。
我个人最喜欢的 3 个更新
如果你问我:PG18 这么多条,哪 3 个最值得立刻关注?我会选:
- AIO 子系统:它不只是"快一点",它改变的是 PG 面对现代存储/现代 I/O 的方式。
- pg_upgrade 保留统计信息:升级体验变得更稳定、更可控。
- pg_stat_io + per-backend I/O:排障与调优终于更"有数据支撑"。
参考链接
- PostgreSQL 18.0 Release Notes:www.postgresql.org/docs/releas...
- io_method(AIO 配置):www.postgresql.org/docs/18/run...
- pg_aios 视图:www.postgresql.org/docs/18/vie...
- pg_stat_io 视图:www.postgresql.org/docs/18/mon...
- 多列索引与 skip scan:www.postgresql.org/docs/18/ind...
- uuidv7():www.postgresql.org/docs/18/fun...
- generated columns(VIRTUAL 默认):www.postgresql.org/docs/18/sql...
- RETURNING old/new:www.postgresql.org/docs/18/dml...
- OAuth:www.postgresql.org/docs/18/aut...
- pg_upgrade:www.postgresql.org/docs/18/pgu...