文章目录
-
- [一、pgbench 基础:安装与默认测试](#一、pgbench 基础:安装与默认测试)
-
- [1.1 安装与验证](#1.1 安装与验证)
- [1.2 默认测试模型(TPC-B 简化版)](#1.2 默认测试模型(TPC-B 简化版))
- [1.3 初始化测试数据](#1.3 初始化测试数据)
- 二、执行压测:核心参数详解
-
- [2.1 基本压测命令](#2.1 基本压测命令)
- [2.2 关键参数说明](#2.2 关键参数说明)
- 三、自定义测试脚本:超越默认模型
-
- [3.1 脚本语法基础](#3.1 脚本语法基础)
- [3.2 编写只读查询脚本(example_ro.sql)](#3.2 编写只读查询脚本(example_ro.sql))
- [3.3 编写混合读写脚本(example_mixed.sql)](#3.3 编写混合读写脚本(example_mixed.sql))
- [3.4 多脚本权重测试](#3.4 多脚本权重测试)
- 四、高级功能与技巧
-
- [4.1 使用内置脚本(-b)](#4.1 使用内置脚本(-b))
- [4.2 控制数据分布](#4.2 控制数据分布)
- [4.3 输出详细统计](#4.3 输出详细统计)
- [4.4 连接池测试](#4.4 连接池测试)
- 五、结果解读与性能分析
-
- [5.1 标准输出示例](#5.1 标准输出示例)
- [5.2 性能瓶颈判断](#5.2 性能瓶颈判断)
- 六、实战案例:配置调优验证
-
- [场景:验证 `synchronous_commit` 对写入性能的影响](#场景:验证
synchronous_commit对写入性能的影响)
- [场景:验证 `synchronous_commit` 对写入性能的影响](#场景:验证
- 七、局限性与替代方案
-
- [7.1 pgbench 的局限](#7.1 pgbench 的局限)
- [7.2 替代工具推荐](#7.2 替代工具推荐)
- 八、实践总结
- 附录:常用命令速查
在数据库性能优化、容量规划、配置验证和版本升级等关键场景中,科学的性能压测 是不可或缺的环节。PostgreSQL 自带的 pgbench 是一款轻量级但功能强大的基准测试工具,能够模拟多客户端并发访问,评估数据库在不同负载下的吞吐量(TPS)、延迟和资源消耗。
尽管 pgbench 默认仅提供简单的 TPC-B 类似测试,但通过自定义脚本、参数调优和结果分析,它可以胜任从基础性能摸底到复杂业务场景仿真的各类压测任务。
本文将全面解析 pgbench 的工作原理、核心参数、脚本编写、高级用法及实战案例,助你构建可复现、可对比、可量化的 PostgreSQL 性能评估体系。
一、pgbench 基础:安装与默认测试
1.1 安装与验证
pgbench 通常随 PostgreSQL 服务端或客户端包一同安装。若未安装,可通过以下方式获取:
- Ubuntu/Debian :
apt install postgresql-contrib - RHEL/CentOS :
yum install postgresql-contrib - 源码编译 :位于
src/bin/pgbench/
验证安装:
bash
pgbench --version
1.2 默认测试模型(TPC-B 简化版)
pgbench 默认模拟一个银行转账场景,涉及四张表:
pgbench_accounts(账户表,主数据)pgbench_branches(分行表)pgbench_tellers(柜员表)pgbench_history(交易历史表)
默认事务逻辑:
sql
BEGIN;
UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
END;
该事务包含 1 次 SELECT、3 次 UPDATE 和 1 次 INSERT,具有典型的 OLTP 特征。
1.3 初始化测试数据
在压测前,需先初始化测试表:
bash
# 创建测试数据库
createdb pgbench_test
# 初始化数据(-s 指定 scale factor)
pgbench -i -s 100 pgbench_test
-s 100表示pgbench_accounts表将包含 100 万行(100 × 10,000);- 其他表行数固定:branches=1×scale,tellers=10×scale,history=0(初始为空)。
注意:初始化过程会创建主键和索引,确保测试环境接近真实。
二、执行压测:核心参数详解
2.1 基本压测命令
bash
pgbench -c 16 -j 4 -T 300 -d pgbench_test
| 参数 | 含义 |
|---|---|
-c 16 |
并发客户端数量(16 个连接) |
-j 4 |
并发线程数(用于驱动客户端,建议 ≤ CPU 核数) |
-T 300 |
测试持续时间(300 秒) |
-d pgbench_test |
目标数据库 |
若不指定
-T或-t(事务总数),pgbench默认只运行 10 秒。
2.2 关键参数说明
(1)客户端与线程模型
-c N:启动 N 个数据库连接(会话);-j M:使用 M 个本地线程驱动这些连接;- 建议 :
-j设为 CPU 物理核数,-c根据目标并发调整(如 2×CPU 核数)。
(2)测试时长与事务数
-T seconds:按时间运行;-t transactions:按事务总数运行;- 二者互斥,推荐使用
-T以获得稳定平均值。
(3)预热与冷却
-P seconds:每 N 秒输出进度报告(便于观察稳定性);- 预热:正式测试前先运行 30--60 秒"热身"测试,使缓存、统计信息稳定;
- 冷却:测试后观察系统恢复情况(非 pgbench 功能,需手动)。
(4)连接与认证
-h host,-p port,-U user:指定连接信息;- 支持
.pgpass文件免密。
三、自定义测试脚本:超越默认模型
3.1 脚本语法基础
pgbench 支持使用类 SQL 脚本定义事务逻辑,支持变量、条件、循环等。
变量:
- 内置变量:
:client_id,:random,:scale等; - 自定义变量:
\set name value
常用函数:
random(a, b):生成 [a, b] 随机整数;random_exponential(a, b, threshold):指数分布随机数;sqrt(x),pow(x,y)等数学函数。
3.2 编写只读查询脚本(example_ro.sql)
sql
\set aid random(1, 1000000 * :scale)
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
执行:
bash
pgbench -c 32 -j 8 -T 300 -f example_ro.sql pgbench_test
3.3 编写混合读写脚本(example_mixed.sql)
sql
\set aid random(1, 1000000 * :scale)
\set bid random(1, 1 * :scale)
\set tid random(1, 10 * :scale)
\set delta random(-5000, 5000)
BEGIN;
UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime)
VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
COMMIT;
3.4 多脚本权重测试
可同时指定多个脚本,并分配执行比例:
bash
pgbench -c 20 -T 300 \
-b select-only@70% \
-f update-heavy.sql@30% \
pgbench_test
或使用文件:
bash
pgbench -c 20 -T 300 \
-f ro.sql@7 \
-f rw.sql@3 \
pgbench_test
表示 70% 执行 ro.sql,30% 执行 rw.sql。
四、高级功能与技巧
4.1 使用内置脚本(-b)
pgbench 提供多种预定义脚本:
| 脚本名 | 描述 |
|---|---|
tpcb-like |
默认脚本(含 BEGIN/COMMIT) |
select-only |
仅 SELECT abalance |
simple-update |
UPDATE accounts + INSERT history(无 branches/tellers 更新) |
aggregates |
包含 COUNT(), SUM() 等聚合 |
示例:
bash
pgbench -c 16 -T 300 -b simple-update pgbench_test
4.2 控制数据分布
- 默认
aid为均匀分布,但真实业务常呈"热点"分布; - 使用
random_exponential模拟长尾效应:
sql
\set aid random_exponential(1, 1000000 * :scale, 10)
4.3 输出详细统计
-r:显示每条 SQL 的平均延迟;--latency-limit=N:丢弃超过 N 毫秒的事务(模拟超时);--rate=N:限制每秒事务数(throttling),用于测试系统在固定负载下的延迟。
4.4 连接池测试
若使用 PgBouncer 等连接池,可测试其性能:
bash
pgbench -h pgbouncer_host -p 6432 -c 100 -j 10 -T 300 pgbench_test
注意:此时 -c 表示应用连接数,实际后端连接由 PgBouncer 控制。
五、结果解读与性能分析
5.1 标准输出示例
transaction type: <custom script>
scaling factor: 100
query mode: simple
number of clients: 16
number of threads: 4
duration: 300 s
number of transactions actually processed: 456789
latency average = 10.520 ms
latency stddev = 2.345 ms
tps = 1522.63 (including connections establishing)
tps = 1525.10 (excluding connections establishing)
关键指标:
- TPS(Transactions Per Second):核心吞吐指标;
- Latency Average:平均延迟,反映响应速度;
- Latency Stddev:延迟标准差,值越大波动越剧烈。
注意:
excluding connections establishing更准确,因连接建立开销不应计入事务性能。
5.2 性能瓶颈判断
| 现象 | 可能原因 |
|---|---|
TPS 随 -c 增加而饱和 |
CPU 或 I/O 瓶颈 |
| 延迟标准差大 | 锁竞争、I/O 抖动 |
| TPS 极低但 CPU 闲置 | 网络延迟、WAL fsync 瓶颈 |
| 内存使用高但 TPS 低 | shared_buffers 过大或 work_mem 不足 |
结合 iostat、vmstat、EXPLAIN 等工具交叉分析。
六、实战案例:配置调优验证
场景:验证 synchronous_commit 对写入性能的影响
步骤:
-
初始化数据:
bashpgbench -i -s 50 pgbench_test -
默认配置测试(synchronous_commit = on):
bashpgbench -c 8 -j 4 -T 120 -b tpcb-like pgbench_test > result_on.log -
修改配置(postgresql.conf):
confsynchronous_commit = off重启或 reload。
-
再次测试:
bashpgbench -c 8 -j 4 -T 120 -b tpcb-like pgbench_test > result_off.log -
对比 TPS:
on:TPS ≈ 800off:TPS ≈ 2500
结论:关闭同步提交可显著提升写入吞吐,但牺牲持久性,适用于可容忍少量丢失的日志场景。
七、局限性与替代方案
7.1 pgbench 的局限
- 无法模拟复杂 JOIN、子查询、窗口函数;
- 不支持 JSON、数组等高级类型操作;
- 事务逻辑简单,难以完全复现业务特征。
7.2 替代工具推荐
| 工具 | 适用场景 |
|---|---|
| sysbench | 支持更灵活的 Lua 脚本,跨数据库 |
| HammerDB | TPC-C/TPC-H 标准测试,图形化界面 |
| JMeter + JDBC | 结合业务代码,高度定制化 |
| 自研压测框架 | 使用 Python/Go 模拟真实 API 调用 |
建议:
pgbench用于快速验证配置和硬件,复杂场景用 JMeter 或 sysbench。
八、实践总结
- 明确测试目标:是测 CPU、I/O、还是网络?
- 数据规模合理 :
-s应使数据大于 shared_buffers,触发真实 I/O; - 预热必不可少:先运行 60 秒再正式测试;
- 多次取平均:避免单次波动影响结论;
- 监控系统资源:同步采集 CPU、I/O、内存数据;
- 保留测试环境:记录 PG 版本、配置、硬件信息,确保可复现;
- 结合业务脚本:尽可能贴近真实 SQL 模式。
附录:常用命令速查
bash
# 初始化 1000 万行数据
pgbench -i -s 1000 mydb
# 32 并发,运行 5 分钟,使用自定义脚本
pgbench -c 32 -j 8 -T 300 -f my_script.sql mydb
# 测试只读性能
pgbench -c 64 -T 120 -b select-only mydb
# 每 10 秒输出进度
pgbench -c 16 -T 300 -P 10 mydb
# 限制 TPS 为 1000,测延迟
pgbench -c 16 -T 300 --rate=1000 mydb
通过系统性使用 pgbench,你可以量化 PostgreSQL 的性能表现,科学评估配置变更、硬件升级或 SQL 优化的效果,为数据库稳定性与高可用提供坚实的数据支撑。