在 PG Summit 2026 上,Richard Yen 将分享如何使用 PostgreSQL 进行硬件与系统基准测试。这个主题的关键并不是证明某块 SSD 能达到产品页面上的峰值,而是回答一个更接近生产的问题:某个数据库工作负载能否在这套系统上稳定运行?它还能扩展多少?最先撞上的瓶颈是什么?
测试硬件组件,不等于测试 PostgreSQL
如果问题是“这块磁盘的顺序读写能力是多少”,fio 是合适的工具;如果问题是“CPU 执行某类运算有多快”,也应该选择针对 CPU 的专用测试工具。这些测试能准确描述单个组件的能力,但它们并不能直接代表 PostgreSQL 集群的表现。
PostgreSQL 的一次真实请求可能同时受到以下因素影响:
- 内存容量与缓存命中率;
- 并发连接、锁竞争和事务调度;
- WAL 写入与刷盘;
- checkpoint 带来的 I/O 峰值;
- autovacuum、统计信息更新和其他后台维护任务;
- 工作负载是读多写少,还是包含大量更新、删除与随机写入。
例如,某块 SSD 标称读写速度很高,但 PostgreSQL 并不一定能复现产品页面上的数字。数据库产生的是混合 I/O,并且访问路径会经过操作系统缓存、PostgreSQL buffer cache、WAL 和后台进程。一个只运行十秒的测试,可能只测到了“缓存已经热起来、维护任务尚未发生”的理想片段。
因此,数据库基准测试中的 checkpoint 和 autovacuum 不是应该删除的噪声,而是系统真实行为的一部分。
把问题从“硬件多快”改成“工作负载能否达标”
更有价值的问题通常是:
这个工作负载在当前系统上能否满足延迟目标?吞吐量还能提升多少?哪个资源会最先饱和?
这要求测试前先定义工作负载。典型场景可能包括:
- OLTP:大量并发、小事务、频繁提交;
- 分析型查询:大范围扫描、聚合和多表连接;
- 文档型数据:宽 JSON 文档、不同压缩特征和较大的行宽;
- 高写入场景:大量 INSERT、UPDATE,或持续增长的 WAL。
工作负载确定后,可以逐步改变并发数、数据规模、缓存条件和 PostgreSQL 配置,同时观察吞吐量、延迟、CPU、内存、I/O、WAL 与维护任务的变化。
当吞吐量不再随并发数增长,或者延迟超过服务目标时,测试才真正开始提供决策信息。第一个饱和的资源也会决定下一步:调整配置、重新设计查询或数据模型、改变基础设施,还是选择不同的硬件。
一个可以改造的 pgbench 基准测试
下面的示例使用 pgbench 创建测试数据,并分别运行预热、测量和高并发阶段。它适合在独立的测试环境中执行;请把连接参数、规模和并发数改成自己的环境,不要直接对生产库运行初始化命令。
#!/usr/bin/env bash
set -euo pipefail
export PGHOST="127.0.0.1"
export PGPORT="5432"
export PGUSER="postgres"
export PGDATABASE="benchdb"
# 只在测试数据库中执行。-s 50 会生成较大的测试数据集。
pgbench -i -s 50 "$PGDATABASE"
# 预热阶段:不计入正式结果,让缓存和连接状态稳定下来。
pgbench -c 32 -j 8 -T 120 --progress=10 "$PGDATABASE"
# 测量阶段:固定并发和时长,记录 TPS 与延迟。
pgbench -c 32 -j 8 -T 600 --progress=10 --latency-limit=100 "$PGDATABASE" \
| tee pgbench-c32-600s.log
# 压力阶段:观察继续增加并发后,吞吐量和延迟如何变化。
pgbench -c 128 -j 16 -T 600 --progress=10 --latency-limit=200 "$PGDATABASE" \
| tee pgbench-c128-600s.log
这个命令并不能自动给出“硬件性能”的最终结论。运行时还需要同步记录系统与数据库指标,例如 CPU 利用率、磁盘读写和队列深度、内存与缓存命中情况、WAL 生成速度、checkpoint 次数、autovacuum 活动,以及锁等待和连接数。
如果要测试更接近业务的场景,可以使用自定义脚本。例如,下面的 custom.sql 模拟一次按用户查找并更新账户余额的事务:
\set user_id random(1, 1000000)
BEGIN;
SELECT id, balance
FROM accounts
WHERE id = :user_id
FOR UPDATE;
UPDATE accounts
SET balance = balance + 1,
updated_at = clock_timestamp()
WHERE id = :user_id;
COMMIT;
运行自定义脚本时,可以使用:
pgbench -c 64 -j 8 -T 600 -f custom.sql --progress=10 "$PGDATABASE"
这里的表结构、数据规模和 SQL 只是示例假设。实际测试应替换为业务中具有代表性的事务,并确认索引、行宽、事务边界和数据分布都符合目标场景。
可信基准测试需要记录什么
一个可信的测试结果不应该只有一个峰值 TPS。至少应记录以下信息:
- PostgreSQL 版本、操作系统、CPU、内存和存储配置;
- 数据集规模、表结构、索引和数据分布;
- 客户端部署位置,以及网络是否跨主机或跨可用区;
- 连接数、线程数、事务类型和并发增长方式;
- 预热时长、正式测量窗口和测试总时长;
- 测试期间的配置变更与维护任务;
- 延迟目标、吞吐量目标和判定标准。
测试时间还应足够长,至少覆盖几次 autovacuum 和 checkpoint 周期。否则,结果可能只反映短暂的缓存状态,而没有反映持续运行时的 I/O 波动与后台维护成本。
还要专门测试过载后的恢复能力:降低并发或停止压力后,延迟是否回落?后台任务是否积压?系统是否会长期停留在退化状态?这类信息往往比单次峰值更接近生产风险。
采用建议:让基准测试服务于决策
硬件组件测试仍然很有价值:需要测存储设备时使用 fio,需要测 CPU 时使用专用工具。但 PostgreSQL 基准测试的目标不同,它关注的是数据库工作负载与整套系统之间的关系。
可以用下面的清单检查一次测试是否足够可靠:
- 是否定义了具体而可重复的工作负载?
- 是否区分了预热阶段与正式测量阶段?
- 是否覆盖了 checkpoint 和 autovacuum?
- 是否同时观察吞吐量、延迟和资源饱和点?
- 是否测试了不同并发度,而不是只跑一个数字?
- 是否记录了配置、数据集、客户端位置和验收标准?
- 是否观察了过载后的恢复情况?
好的基准测试不是为了制造一个漂亮的数字,而是为了帮助团队判断:系统当前能承受什么、瓶颈在哪里,以及下一笔容量或硬件投入应该解决什么问题。这也是 PG Summit 2026 演讲中将围绕 HammerDB、pgbench、工作负载设计和瓶颈证据展开的核心方向。