跳至内容
27 精益求精:参数调优与资源治理

第 27 章 精益求精:参数调优与资源治理

调优不是把一份“最佳参数”复制到 postgresql.conf

同一个参数变化可能:

让一条查询更快
  但让十条并发查询触发 OOM

减少 WAL
  但增加 primary CPU 和 replica replay CPU

提高单条分析查询速度
  但占满 parallel worker,让 OLTP tail latency 变差

增加连接槽
  但把 pool 中可控的队列搬进数据库

在 benchmark 中提高 TPS
  但降低 durability、HA headroom 或 recovery predictability

本章用一条严格的推理链替代参数清单:

service objective
  -> observed bottleneck or resource risk
      -> parameter mechanism
          -> scope and precedence
              -> one-factor experiment
                  -> benefit + non-regression + failure behavior
                      -> rollback
                          -> ADR

如果中间缺了一环,默认动作不是“先改了看看”,而是补证据。

参数不是独立旋钮

PostgreSQL 参数形成资源系统:

shared_buffers
  <-> OS page cache
  <-> checkpoint dirty-page work
  <-> max_wal_size

work_mem
  × active operations
  × sessions
  × parallel processes
  × hash_mem_multiplier

max_connections
  <-> backend/shared memory
  <-> pool queue
  <-> lock/context-switch pressure

parallel workers
  <-> CPU
  <-> work_mem
  <-> worker pool
  <-> other queries and maintenance

checkpoint / WAL
  <-> write smoothing
  <-> WAL volume
  <-> archive/replica
  <-> crash recovery time

所以本章不按字母解释 GUC,而按资源预算和失效机制组织。

本章实验故意得到“拒绝改参”

第 26 章参考 run 提供了几个事实:

  • c8 时 server work ratio 约 84%,client 未先饱和;
  • workload 使用 prepared protocol;
  • 六个 cell 的 temp bytes 全为零;
  • L 档有 block read,但 server iowait 很低;
  • 只有 c1/c8,精确 knee 未知;
  • production sustainable TPS 仍为 null

这些事实不支持

increase work_mem
increase shared_buffers
increase max_connections
disable synchronous_commit

它们只使一个假设值得被证伪:

prepared OLTP 在 plan_cache_mode=auto 下是否仍承担了足够的 custom planning 成本,使 force_generic_plan 获得至少 2% 的稳定收益?

正式实验只改变这个参数,而且只用 PGOPTIONS 改 benchmark session:

baseline   plan_cache_mode=auto
candidate  plan_cache_mode=force_generic_plan

固定 M 数据、8 clients、prepared、50/30/20 mix;五组 paired repetition 使用相同 seed,A/B 顺序交错。共 10 次 12 秒 measured run、357,685 笔事务:

armmedian TPSpooled p50pooled p95pooled p99failure/late/skipped
auto2,981.721.279 ms9.217 ms13.127 ms0
force_generic_plan3,051.721.285 ms9.135 ms12.933 ms0

只看两个 median,candidate 好像快 2.35%。但正确的配对分析是:

paired TPS ratio median       1.00735
bootstrap 95% interval        [0.98082, 1.02775]
candidate / baseline p95      0.99110
required bootstrap lower      >= 1.02

candidate 没有证明至少 2% 的稳定收益。plan probe 还发现:

auto:
  first 5 custom + next 5 generic

force_generic_plan:
  10 generic + 0 custom

PostgreSQL 的 auto 已经为这两类稳定 plan 自动转向 generic。强制 generic 只省掉 少量早期 planning,却可能伤害参数敏感查询。最终 ADR:

decision                    reject-persistent-change
persistent change applied   false
production gate             pending

这不是“没有调优成果”。它避免了一项没有稳定收益、却扩大 plan risk 的持久变更。

公共结果见 tuning-run.json,完整安全边界见 lab-contract.md

本章学习成果

完成本章后,你应该能:

  1. 从 SLO、bottleneck 和 non-regression 指标写调优假设;
  2. 区分参数、SQL/schema、workload 与 topology 问题;
  3. 为 shared memory、per-operation memory、maintenance 与 OS 留出完整预算;
  4. 解释 work_mem × 节点 × 并发 × parallel process 的放大;
  5. 用 WAL、checkpointer、I/O 与 recovery evidence 调整 checkpoint;
  6. 区分 effective_cache_size estimate 与真实 cache allocation;
  7. 校准 cost parameter,而不是用 enable_seqscan=off 长期逼 planner;
  8. 计算 parallel worker 的 cluster budget 和降级行为;
  9. 把 connection limit 与 pool/admission、reserved slot 和 emergency access 联动;
  10. pg_settings.context/source/pending_restart 判断变更方式;
  11. pg_file_settings 找出 syntax error 与被后项覆盖的配置;
  12. 理解 system、database、role、role-in-database、session、transaction 的覆盖关系;
  13. 用 Pigsty template、pg_parameters 与 IaC 保持 desired state;
  14. 在 reload/restart/rolling change 前写 failure、rollback 与 validation;
  15. 接受“拒绝修改”也是合格 ADR。

本章目录

27.1 调优是一套实验方法

27.2 内存预算

27.3 WAL、检查点与写入平滑

27.4 规划器、并行与连接参数

27.5 参数作用域与变更方式

27.6 模板参数与集群变更

27.7 实战:只调一个已证实的瓶颈

阅读路线

应用开发者:

27.1 -> 27.2.2 -> 27.4 -> 27.5.2 -> 27.7

重点是 per-query memory、plan、timeout、role/database scope 和 A/B。

平台工程师:

27.1 -> 27.2 -> 27.3 -> 27.5 -> 27.6 -> 27.7

重点是 cluster resource budget、WAL/recovery、配置来源、IaC 与 rolling risk。

两条路线必须合流:应用知道 transaction 与 query shape,平台知道 failure domain 与 global resource envelope;任何一方单独调参都容易优化局部、破坏整体。

实验文件

static/labs/ch27/
├── requirements.json
├── parameter-candidates.json
├── change-contract.json
├── negative-cases.json
├── topology.mmd
├── lab-contract.md
├── setup.sql
├── reset-run.sql
├── read-product.sql
├── read-order.sql
├── place-order.sql
├── plan-probe-counts.sql
├── plan-probe-product.sql
├── plan-probe-order.sql
├── remote_experiment.py
├── capture.py
├── exercise.py
├── validate.py
├── review.py
├── task.sh
└── tuning-run.json

实验:

  • 只测试一个参数;
  • 只在 benchmark session 生效;
  • 不使用 ALTER SYSTEM、DCS edit、reload/restart;
  • 保留 raw transaction log 与 plan-shape evidence;
  • 用 28 个对抗变体验证 target、scope、配对、quantile、decision 和 cleanup;
  • 专用 database、role 与远端临时目录全部清理;
  • 不管 candidate 接受或拒绝,production gate 都保持 pending

参考资料


上一章:胸有成竹:容量规划与压测基线 · 返回下卷导读 · 下一章:除旧布新:VACUUM、冻结与膨胀治理 · 查看全书目录 · 查看索引中心

最后更新于