PostgreSQL 18 异步 IO 完全指南:配置、测试与调优
PostgreSQL 18 异步 I/O 让数据库并发提交多个读请求,云存储等高延迟环境下读密集负载可提速 2-3 倍。本文讲清 worker/io_uring/sync 三种模式、参数配置、基准测试方法,以及异步 I/O 无效的三种场景。
PostgreSQL 18 的异步 I/O是多年来读取路径最大的一次改造。以前数据库读盘是一个请求等一个结果,靠操作系统预读(readahead)猜下一步要哪块数据——但 OS 看不懂查询计划,经常猜错。异步 I/O 让 PostgreSQL 基于查询计划自己决定预读,并并发提交多个读请求。在云厂商的网络存储这类高延迟环境,读密集负载可获 2-3 倍提升。
当前支持异步加速的操作:顺序扫描、位图堆扫描、VACUUM 等维护操作——都是访问模式可预测、预读命中率高的场景。
三种 I/O 模式
通过 io_method 参数控制:
| 模式 | 机制 | 适用 |
|---|---|---|
worker(默认) |
专门的 I/O worker 后台进程代为执行读请求 | 所有平台,开箱即用 |
io_uring |
走 Linux 5.1+ 内核的 io_uring 接口,共享环形缓冲直交内核,开销更低 | Linux 且编译时带 --with-liburing |
sync |
退回 17 的同步行为 | 排障和对比测试用 |
检查 worker 进程(默认 io_workers = 3):
ps aux | grep "io worker" | grep -v grep
# postgres: 18/main: io worker 0 / 1 / 2
检查能否用 io_uring:
uname -r # 内核 ≥ 5.1
ldd /usr/lib/postgresql/18/bin/postgres | grep uring # 有 liburing 即支持
没有 liburing 也不用纠结——worker 模式已能拿到大部分收益。
上手测试流程
-- 1. 建专用测试库
-- sudo -u postgres createdb aio_test && sudo -u postgres psql aio_test
-- 2. 查看当前模式
SHOW io_method;
-- 3. 建大于内存的测试表(关键!异步 I/O 的收益只在真正读盘时体现)
测试要点:测试表必须大于可用内存。数据全在缓存里时根本没有磁盘 I/O,异步优化无从体现——这是测评结论两极分化的主要原因。
基准测试方法:先用 io_method = 'sync' 跑一遍目标查询记录耗时,再切 worker(和 io_uring,若可用)各跑一遍对比。跑前清缓存或重启,避免热缓存污染结果。
参数调优与固化
测试出最优值后写进 postgresql.conf:
effective_io_concurrency = 32 # 常规查询的并发度,按测试结果定
maintenance_io_concurrency = 100 # VACUUM/建索引等维护任务,可给更高
io_method = 'worker' # 支持则换 'io_uring'
io_workers = 3 # I/O worker 进程数
维护类并发度通常给得更高,因为 VACUUM、CREATE INDEX 多在业务低峰跑。改完需重启生效。
异步 I/O 帮不上忙的三种场景
别对它抱不切实际的期待,先判断你的瓶颈在哪:
1. 缓存命中率本来就高
SELECT
sum(heap_blks_read) AS disk_reads,
sum(heap_blks_hit) AS cache_hits,
round(sum(heap_blks_hit)::numeric /
nullif(sum(heap_blks_hit) + sum(heap_blks_read), 0) * 100, 2) AS hit_ratio
FROM pg_statio_user_tables;
命中率 99%+ 说明数据基本都在内存,没什么盘可读,异步 I/O 自然无用武之地。
2. CPU 密集型查询:排序、聚合、大连接吃掉大部分时间的分析型查询,瓶颈在 CPU 不在 I/O。看执行计划里 buffer 读取占比就知道。
3. 存储已打满:iostat -x 2 看 %util 长期 100% 且 await 很高,说明硬件已到极限——异步 I/O 只会让你更快撞到天花板,不会提高天花板。
排障速查
- 切换模式没效果 → 先查缓存命中率(见上);再确认测试数据量大于内存;
- io_uring 不生效 → 检查内核版本和 liburing 编译支持,退回
worker验证; - 改了参数没变化 →
io_method等参数需重启生效,会话级SET只对当前连接有效; - 想确认异步在工作 → 查
pg_aios视图看活跃的异步文件句柄。
观测云对照
调 I/O 参数是"盲人摸象"还是"有的放矢",取决于你有没有持续的数据库指标。观测云 DataKit 采集 PostgreSQL 的连接、事务、缓存命中率、慢查询、锁等待等指标,配合主机层面的磁盘 util/await 指标,可以在同一仪表板上对照"参数调整 → I/O 行为 → 查询延迟"的完整因果链;监控器可对慢查询率、磁盘 util 设阈值告警,防止调优后的回退无人察觉。 1 2
常见问题(FAQ)
Q:异步 I/O 对写入有帮助吗?
目前主要针对读操作(顺序扫描、位图堆扫描、VACUUM)。写入路径的异步化是后续版本的方向。
Q:生产环境推荐 worker 还是 io_uring?
内核和编译支持都满足时优先 io_uring(开销更低);不确定就用默认 worker,收益差距不大,稳定性更有把握。
Q:升级 18 后什么都不用改就有收益吗?
是。默认 io_method = 'worker' 已开启异步读。调参只是锦上添花。
Q:云 RDS 上能用吗?
取决于厂商是否跟进到 PostgreSQL 18 并开放相关参数。网络存储恰好是异步 I/O 收益最大的场景,值得关注所用云厂商的版本支持节奏。