PostgreSQL 完全指南 / 20 - 性能测试
第 20 章 · 性能测试
本章介绍 pgbench、压测方法论和连接池对比测试。
20.1 pgbench(内置压测工具)
# 初始化测试数据
pgbench -i -s 50 mydb # -s 50 表示 50 倍缩放因子(约 500 万行)
# 标准测试(SELECT、UPDATE、INSERT)
pgbench -c 10 -j 4 -T 60 mydb
# -c 10: 10 个并发客户端
# -j 4: 4 个工作线程
# -T 60: 运行 60 秒
# 只读测试
pgbench -c 10 -T 60 -S mydb
# 自定义脚本
cat > my_script.sql << 'EOF'
\set aid random(1, 100000 * :scale)
\set bid random(1, 1 * :scale)
\set tid random(1, 10 * :scale)
\set delta random(-5000, 5000)
BEGIN;
UPDATE pgbench_accounts SET balance = balance + :delta WHERE aid = :aid;
SELECT balance FROM pgbench_accounts WHERE aid = :aid;
UPDATE pgbench_tellers SET balance = balance + :delta WHERE tid = :tid;
UPDATE pgbench_branches SET balance = balance + :delta WHERE bid = :bid;
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
END;
EOF
pgbench -c 20 -j 4 -T 120 -f my_script.sql mydb
pgbench 输出解读
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 50
query mode: simple
number of clients: 10
number of threads: 4
duration: 60 s
number of transactions actually processed: 12345
latency average = 4.860 ms
latency stddev = 2.340 ms
initial connection time = 15.234 ms
tps = 2058.432 (without initial connection time)
| 指标 | 含义 | 关注点 |
|---|
tps | 每秒事务数 | 越高越好 |
latency average | 平均延迟 | 越低越好 |
latency stddev | 延迟标准差 | 越小越稳定 |
initial connection time | 连接建立时间 | 评估连接池效果 |
20.2 sysbench(通用压测工具)
# 安装
sudo apt install sysbench
# OLTP 读写测试
sysbench oltp_read_write \
--pgsql-host=127.0.0.1 \
--pgsql-port=5432 \
--pgsql-user=postgres \
--pgsql-password=password \
--pgsql-db=mydb \
--db-driver=pgsql \
--tables=10 \
--table-size=100000 \
--threads=16 \
--time=300 \
--report-interval=10 \
run
# 纯读测试
sysbench oltp_read_only ... run
# 纯写测试
sysbench oltp_write_only ... run
# 准备数据
sysbench oltp_read_write ... prepare
# 清理
sysbench oltp_read_write ... cleanup
20.3 压测方法论
压测流程
1. 明确目标
├── 吞吐量(TPS/QPS)目标
├── 延迟目标(P99 < 100ms)
└── 并发用户数
2. 环境准备
├── 使用生产相似的硬件/配置
├── 使用生产规模的数据量
└── 确保网络/存储一致
3. 预热(Warmup)
└── 先运行 5-10 分钟让缓存预热
4. 阶梯测试
├── 10 并发 → 稳定后记录 TPS
├── 50 并发 → 稳定后记录
├── 100 并发 → 稳定后记录
└── 找到拐点(性能下降的并发数)
5. 持续压力测试
└── 在目标并发下运行 30 分钟以上
6. 分析结果
├── TPS 趋势
├── 延迟分布(P50/P95/P99)
├── 资源使用(CPU/内存/磁盘IO)
└── 瓶颈分析
关键指标
| 指标 | 说明 | 工具 |
|---|
| TPS | 每秒事务数 | pgbench/sysbench |
| QPS | 每秒查询数 | pgbench |
| P50/P95/P99 延迟 | 百分位延迟 | pgbench/sysbench |
| CPU 使用率 | 服务器 CPU | top/htop/iostat |
| 内存使用 | Shared Buffers 命中率 | pg_stat_database |
| 磁盘 IOPS | 读写 IOPS | iostat |
| 连接数 | 活跃/空闲连接 | pg_stat_activity |
20.4 连接池对比测试
-- 创建测试场景:不同连接池模式的对比
-- 测试脚本:逐步增加并发
-- 直连(无连接池)
pgbench -c 50 -T 60 -h 127.0.0.1 -p 5432 mydb
-- PgBouncer session 模式
pgbench -c 50 -T 60 -h 127.0.0.1 -p 6432 mydb
-- PgBouncer transaction 模式
pgbench -c 50 -T 60 -h 127.0.0.1 -p 6433 mydb
| 配置 | 优势 | 劣势 |
|---|
| 无连接池 | 简单 | 连接数受限,fork 开销大 |
| session 模式 | 会话级功能完整 | 复用率低 |
| transaction 模式 | 最高复用率 | 不支持 LISTEN/NOTIFY |
| statement 模式 | 极高复用率 | 不支持多语句事务 |
20.5 性能优化前后对比
-- 优化前
EXPLAIN ANALYZE SELECT * FROM orders WHERE customer_id = 12345;
-- Seq Scan on orders (cost=0.00..125000.00 rows=50 width=56)
-- Execution Time: 850.000 ms
-- 创建索引后
CREATE INDEX idx_orders_customer ON orders (customer_id);
EXPLAIN ANALYZE SELECT * FROM orders WHERE customer_id = 12345;
-- Index Scan using idx_orders_customer on orders (cost=0.43..12.50 rows=50 width=56)
-- Execution Time: 0.500 ms
业务场景
| 场景 | 压测方法 |
|---|
| 新系统上线 | pgbench 标准测试 + 自定义脚本 |
| 版本升级验证 | 优化前后 TPS/延迟对比 |
| 容量规划 | 阶梯测试找拐点 |
| 连接池选型 | 不同并发下的 TPS 对比 |
扩展阅读