聚焦六大功能:PostgreSQL 18 新特性深度解析
PostgreSQL 全球开发组于 2025 年 5 月 8 日发布了 PostgreSQL 18 的首个 Beta 版本,正式版也已于 9 月 25 日正式上线。本文 IvorySQL 社区将为大家拆解 PostgreSQL 18 的六大亮点特性。
一、PG 异步 I/O(AIO)框架:迈出打破同步阻塞瓶颈的第一步
PostgreSQL 18 全新引入异步 I/O 子系统。新机制允许特定场景下并行执行多个异步预读操作,CPU 无需等待数据返回即可继续推进查询,一定程度上降低了等待损耗。此框架为 PG 未来更深入更彻底的异步 I/O 性能优化奠定基础,迈出了第一步。
核心提升场景
【当前 仅实现异步读,没有实现异步写】 所有 Seq Scan 场景下通过适配过异步 I/O 的 ReadStream 设施可实现并行化顺序预读,提升 Seq Scan 的性能,效果好于原有 posix_fadvice 的建议性预读。尤其在云存储场景下单次阻塞读 I/O 相比本地 I/O 所需时间更长,异步 I/O 加持下的并行化预读的优势更加明显。目前异步 I/O 已支持顺序扫描、位图堆扫描和 VACUUM 操作的异步读取,早期测试显示,读取密集型查询性能可提升 2-3 倍。
如图所示:

使用了异步 I/O 的 ReadStream 机制可以在收到读请求后异步地预读后续可能使用的 buffer。而在使用同步 I/O 方式在每次请求读取 buffer 时,都要等待 I/O 操作完成,这样降低了系统吞吐量。
使用方法
# - I/O -
#backend_flush_after = 0 # measured in pages, 0 disables
effective_io_concurrency = 300 # 1-1000; 0 disables issuing multiple simultaneous IO requests
maintenance_io_concurrency = 300 # 1-1000; same as effective_io_concurrency
io_max_combine_limit = 256kB # usually 1-128 blocks (depends on OS)
# (change requires restart)
io_combine_limit = 256kB # usually 1-128 blocks (depends on OS)
io_method = io_uring # worker, io_uring, sync
# (change requires restart)
io_max_concurrency = 128 # Max number of IOs that one process
# can execute simultaneously
# -1 sets based on shared_buffers
# (change requires restart)
#io_workers = 3 # 1-32;
用户可选择三种不同的 io_method 启用异步 I/O,分别是:
worker若干后台 I/O workers 接收处理后端进程的 I/O 请求。io_uringLinux 系统中 io_uring 子系统通过操作系统内核线程处理 PG 的 I/O 请求。sync满足异步 I/O 框架接口要求的同步 I/O。
要启用异步 I/O,用户需要根据自身情况设定上述 GUC 参数。其中每个进程能够拥有的最大异步 I/O 句柄为 io_max_concurrency,用户可以将其置 -1,使数据库自行选择合适的值。若自行选择的值太大,则可能因为异步 I/O 所占空间太大而无法启动数据库;若自行选择的值太小则无法完全发挥出异步 I/O 性能。
启动数据库后,用户可通过 pg_aios 视图实时地获取当前系统异步 I/O 执行状况:
postgres=# select * from pg_aios;
-[ RECORD 1 ]---+-------------------------------------------
pid | 85834
io_id | 14208
io_generation | 204
state | SUBMITTED
operation | readv
off | 116252672
length | 8192
target | smgr
handle_data_len | 1
raw_result |
result | UNKNOWN
target_desc | block 14191 in file "base/5/16427"
f_sync | f
f_localmem | f
f_buffered | t
...
各列含义详见官方文档。
框架设计
PG 18 引入异步 I/O 框架,支持通过 GUC 参数灵活配置异步 I/O:包括实现方式(io_method,可选 worker、io_uring 或 sync)、并发规模(如 *_io_concurrency、io_max_concurrency)及实现相关参数(如 io_workers)。
该框架对 I/O 目标(当前支持 smgr,未来计划支持 WAL)和不同阶段、不同数据源(shared buffer/local buffer)的行为进行了抽象(通过 PgAioHandleCallbacks 结构),以支持后续扩展。相关内存于启动时在共享内存中分配,后续不再缩放。进程按编号访问所属异步 I/O 资源,句柄通过 generation 号标记复用。
目前该版本异步 I/O 主要提供对 smgr 的异步读支持,尚不支持 WAL 异步读写,smgr 的异步写入功能仍在开发中。
对原有设施的修改
- 扩展 smgr 接口:新增
smgr_startreadv方法以支持异步读取。 - 实现回调结构:smgr 需实现
PgAioTargetInfo和PgAioHandleCallBacks回调结构。 - 适配现有模块:smgr 和 buffer manager 等模块需填充异步 I/O 抽象结构以兼容框架。
- PG 临界区处理:同步 I/O 可在 PG 临界区内发起;异步 I/O 因分段执行且带回调,需移除回调中可能失败的操作(临界区内一切操作不能失败,如用
RelPathStr替代 palloc 的char*字符串)以确保安全。 - 优化上层接口:利用异步 I/O 改造 ReadStream 等接口,实现真预读,大幅提升顺序扫描、pg_prewarm 及 ANALYZE 等操作的 I/O 性能,效果优于原有 posix_fadvise 方案。
使用注意及未来展望
- **io_uring 需要较新内核:**旧版 Linux Kernel 不支持 io_uring。某些早期版本内核虽然支持 io_uring,但功能和性能表现与新内核有 一定差距。
- 架构限制并发粒度:受多进程架构所限,PG 异步 I/O 期间可并行运行的计算任务较少,难以实现更细粒度的任务级异步。当前主要性能收益集中于ReadStream 顺序预读及等并行 I/O 操作。
- 未来可能的性能提升:Linux io_uring 支持直接 I/O(DIO)特性,为在 PG 中启用 DIO 奠定基础。未来启用直接 I/O 可免除双重 buffer(OS 层面对 I/O 数据进行 buffer,PG 层面对 I/O 进行 buffer)以减少不必要的数据复制。在高速 NVMe 上还配合 DIO 启用IORING_SETUP_IOPOLL选项使用轮训方式检查 I/O 完成情况,还可以进一步提升性能。
- 未来更多的异步 I/O 后端:除了
sync模式,正式版的 PostgreSQL 18 仅支持worker和io_uring两种异步 I/O 后端。目前异步 I/O 框架设计已基本完备,未来版本有望支持 Windows IORing,IOCP,以及 Posix 异步 I/O 等 I/O 后端,为用户提供更多选择。
小结
PostgreSQL 18 异步 I/O 框架提升数据库系统 I/O 能力,同时也增强了 PostgreSQL 架构的可扩展性,用户只需要根据自身情况修改 GUC 参数即可获取到异步 I/O 带来的好处。目前异步 I/O 框架设计基本完备,后期支持其他异步 I/O 后端也将非常方便。任意平台 Postgres 用户可以尝试 io_method = worker或者sync 若要在非官方适配 io_uring 的旧 Linux 内核发行版上使用 io_uring 后端,需要进行充分测试后再使用。
二、 跳跃式扫描:让 B 树索引 “提速换挡”
在 PostgreSQL 18 之前的版本中,多列 B 树索引可用于包含该索引中任意子集列的查询条件,在对起始(最左侧)列施加约束时最为高效。对前导列的等式约束,加上对第一个不带有等式约束的列的任何不等式约束,用于限制要扫描的索引部分。
例如,给定一个基于(a,b,c)非空字段的升序索引和查询条件 WHERE a = 5 AND b >= 42 AND c < 77,该索引将从具有 a = 5 和 b = 42 的第一个条目开始扫描,一直扫描到最后具有 a = 5 的条目。 具有 c >= 77 的索引条目将被跳过,但它们仍需扫描。
原则上,这种索引可以用于对 b 和/或 c 有约束条件而对 a 没有约束条件的查询——但必须扫描整个索引,所以在大多数情况下优化器更倾向于对表进行顺序扫描表,而非利用索引扫描。
核心提升场景
从 PostgreSQL 18 开始:
如果 B 树索引扫描能够应用跳跃式扫描(SKIP SCAN),在遍历索引时应用每个列的约束,可以减少索引的读取。跳跃式扫描的工作原理是内部生成一个动态等式约束,该约束与索引列中的每个可能值相匹配。
效果测试
对比版本:
PostgreSQL 17 vs PostgreSQL 18
