上一篇文章简单介绍AIO的概述及在PG 18beta1 下环境搭建准备:PG 18beta1 真正的AIO来了 | 感慨&环境准备
本文将回顾AIO在PG近几个版本的发展历程及在18里的最新表现。
AIO 与 DIO
上篇文章提到18提交的AIO相关特性有个README.md,推荐大家详细阅读下:PG为什么要设计AIO、为什么要设计DIO,为什么要同时设计DIO和AIO。
简单的小结:AIO和DIO的愿景是为了提高吞吐量、降低延迟、减少抖动、减少双缓存的影响。目前它俩相辅相成,AIO已完全实现读操作,DIO有一些成效,但未完全成熟。
参考阅读链接:
https://github.com/postgres/postgres/commit/fdd146a8ef2bc0c24e8d27e3773feeb8ef0a9c25
PG 15~18实现细节
- PG 15在崩溃恢复及流复制场景性能有所提升,得益于Recovery Prefetching特性,可通过GUC参数recovery_prefetch进行调节来降低流复制延迟。
- PG 16对DIO做了些铺垫性的基础工作,使用debug_id_direct参数可直接体验DIO开发特性,且对数据文件、WAL写操作及init初始化可进行调试观察。
- PG 17提供了更快的Streaming APIs,一次系统调用可读多个page页

可回顾PG 17新特性分享里的这页PPT

当时我在本地虚拟机1C1G环境下,对比测试PG 16,PG 17有60~70ms的提升。
17版本开始,sequential scans & ANALYZE & pg_prewarm这三种操作将受益于内部的API接口,性能会有一定提升。
- PG 18实现了真正的asynchronous I/O,且提供了两种实现方式
基于Linux内核原生的io_uring或数据库自身多进程的io worker方式
io_uring相比io worker方式的优势:更适合大量小IO场景,因为io worker的方案对于上下文切换的开销是不能被忽略的,并且workers的进程数量也是有限制的(默认值为3,可调节范围为1~32)。
而从18开始,bitmap heap scan & vacuum这些操作将受益于Streaming read接口,详细介绍请参考社区特性提交链接:
VACUUM first phase:
https://github.com/postgres/postgres/commit/9256822608f3b0636cfd88c3436cdceda7003cf3
VACUUM third phase:
https://github.com/postgres/postgres/commit/c3e775e608f2a6d0bcfba147bf08a506827cc567
BitmapHeapScan commit:
https://github.com/postgres/postgres/commit/2b73a8cd33b745c5b8a7f44322f86642519e3a40
AIO batchmode commit:
https://github.com/postgres/postgres/commit/67be093562b6b345c170417312dff22f467055ba
scan bitmap next block commit:
https://github.com/postgres/postgres/commit/c3953226a07527a1e2f7f410b83e1a7021f42888
PG 18 AIO:io_uring & io worker
上篇文章介绍了使用io uring方式时,编译选项需要开启–with-liburing,而默认的io worker方式则无任何编译依赖。
使用默认配置初始化启动数据库,感受io worker方式
initdb -D /opt/postgres/pgdata1800 pg_ctl start -D /opt/postgres/pgdata1800
接着查看进程,可以观察到三个io worker进程

io_method默认配置为worker,且io_workers配置值为3

PG 18 AIO参考测试
AWS c7i.8xlarge 32 vCPUs, 64 GB RAM,a dedicated 100GB io2 EBS volume, with 20,000 provisioned IOPS. The test table was 3.5GB.
测试用例如下:
CREATE TABLE test(id int);
INSERT INTO test SELECT * FROM generate_series(0, 100000000);
测试语句为3.5GB全表的count查询
SELECT COUNT(*) FROM test;

参考链接:
https://pganalyze.com/blog/postgres-18-async-io
参考上面的测试用例,我在低配的本地环境对比测试了三种场景的Cold Cache,io worker配置也能看到明显的效果,下面时间记录单位为秒。

每种场景测试了三次,每次测试前都重启数据库且清空Cache。
PG 18 AIO监控:pg_aios
新的AIO方式虽然带来了一些性能的增益,但我们对数据库进行监控,观察等待事件及时间消耗时也许会面临一些困惑,尤其是首次接触使用新版本时。
例如下面我们通过常规的活动会话视图pg_stat_activity观察后台进程的IO时,由于IO操作被委派给I/O worker进程,等待事件需要观察I/O worker进程的等待事件。
SELECT backend_type, query, state, wait_event_type, wait_event
FROM pg_stat_activity
WHERE backend_type = 'client backend' OR backend_type = 'io worker';

而如果我们使用io_method = io_uring,此时IO读操作直接提交给os内核,由内核异步完成,此时观测活动会话视图则无效,需要使用新的pg_aios视图。
SELECT * FROM pg_aios;
除此以外,当我们查看一些慢语句的执行计划时,AIO特性可能会隐藏一些IO开销,会给问题分析带来一些新的挑战,这点值得我们注意。
最后:AIO将是PG 18里一个璀璨的亮点特性,大家可以提前测验起来~




