这是《PostgreSQL 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 性能调优是系统化工程:先定义目标和基线,再定位瓶颈,最后通过压测验证配置和 SQL 改动。
26.1 调优流程
确定 SLO
-> 建立基线
-> 采集资源和 SQL
-> 定位瓶颈
-> 一次改一个变量
-> 压测
-> 固化配置和规范
26.2 参数分层
| 层 | 参数 |
|---|---|
| 连接 | max_connections、superuser_reserved_connections |
| 内存 | shared_buffers、work_mem、maintenance_work_mem |
| WAL | max_wal_size、checkpoint_timeout、synchronous_commit |
| 查询 | default_statistics_target、random_page_cost |
| 自动清理 | autovacuum_* |
| 日志 | log_min_duration_statement |
26.3 连接池
连接不是越多越好。应用应使用 PgBouncer 或应用内连接池。
max_connections = 200
PgBouncer pool = 50-100,按业务拆池
事务级或会话级模式按语义选择
事务级 pooling 不支持依赖连接状态的特性,如 prepared statement 的部分行为、SET SESSION、 advisory lock 语义。
26.4 内存参数
ALTER SYSTEM SET shared_buffers = '4GB';
ALTER SYSTEM SET effective_cache_size = '12GB';
ALTER SYSTEM SET work_mem = '32MB';
ALTER SYSTEM SET maintenance_work_mem = '512MB';
SELECT pg_reload_conf();
ALTER SYSTEM 写入自动配置文件,仍要纳入版本管理。
26.5 IO 调优
关注:
- 数据盘类型;
- WAL 与数据是否分离;
- full_page_writes;
- 检查点分布;
- bgwriter;
- 表和索引布局;
- 临时文件位置。
查看 IO 等待:
SELECT wait_event_type, wait_event, count(*)
FROM pg_stat_activity
WHERE state <> 'idle'
GROUP BY 1, 2;
26.6 SQL 调优
优先级:
- 修复缺索引;
- 修复统计信息;
- 减少扫描列和行;
- 优化排序聚合;
- 控制返回结果;
- 消除 N+1;
- 使用绑定参数;
- 缓存稳定结果。
26.7 批量作业
大作业分批:
WITH batch AS (
SELECT id
FROM tasks
WHERE status = 'NEW'
ORDER BY id
LIMIT 1000
FOR UPDATE SKIP LOCKED
)
UPDATE tasks t
SET status = 'RUNNING'
FROM batch
WHERE t.id = batch.id
RETURNING t.id;
26.8 基准测试
pgbench -i -s 10 testdb
pgbench -c 20 -j 4 -T 120 testdb
测试前记录:
- 数据规模;
- 参数;
- 硬件;
- 查询集;
- 并发模型;
- 系统指标。
本章小结
性能调优不能脱离负载模型。先治理 SQL 和索引,再谨慎调整内存、WAL 和 autovacuum,并用连接池和压测验证并发能力。
思考题
- 为什么 max_connections 不是越大越好?
- 事务级连接池有什么限制?
- work_mem 调大的风险是什么?
- 批量任务为什么分批提交?
- 如何建立可信压测基线?