目录

pgsql-28 配置参数调优

1. 概述

PostgreSQL 默认配置非常保守(为了能在小机器上启动),生产环境几乎必须调优。本篇按"内存 → WAL/检查点 → 并发 → autovacuum → 规划器"梳理最核心的参数,给出经验公式。

对比 MySQL:MySQL 调优的核心是 innodb_buffer_pool_size(通常设为 60-70% 内存,一块大缓冲池);PostgreSQL 的内存模型不同——它依赖操作系统的页缓存shared_buffers 只设中等大小(约 25% 内存),把剩余内存留给 OS 缓存。这是两者调优哲学最大的区别。

1.1 参数管理

-- 查看参数
SHOW shared_buffers;
SELECT name, setting, unit, context FROM pg_settings WHERE name = 'work_mem';

-- 修改(PG 支持在线改,部分需重启)
ALTER SYSTEM SET work_mem = '32MB';   -- 写入 postgresql.auto.conf
SELECT pg_reload_conf();              -- 重载(对需重启的参数无效)

context 列决定改后是否需重启:postmaster=需重启,sighup=reload 即可,user=会话级可随时改。

2. 内存参数(最重要)

2.1 shared_buffers

PostgreSQL 自己的共享缓冲池,缓存数据页。

  • 经验值:物理内存的 25%(如 32GB 内存 → 8GB)。
  • 不宜过大:PG 还依赖 OS 页缓存,设太高反而与 OS 缓存重复浪费,且加大检查点刷盘压力。
shared_buffers = 8GB

2.2 effective_cache_size

告诉优化器"整个系统大约有多少内存可用于缓存"(shared_buffers + OS 缓存的估计值)。它不实际分配内存,只影响优化器判断"索引扫描 vs 全表扫描"的成本。

  • 经验值:物理内存的 50-75%
effective_cache_size = 24GB

2.3 work_mem(易踩坑)

单个查询操作(排序 Sort、哈希 Hash Join、聚合)可用的内存。超出则用磁盘临时文件(慢)。

  • ⚠️ 这是每操作、每连接的量!一个复杂查询可能有多个排序/哈希,一个高并发场景 = work_mem × 操作数 × 并发连接数,设太大易 OOM。
  • 经验起点: (可用内存 - shared_buffers) / (max_connections × 2~3),常见 16-64MB。
  • 技巧:全局设小,对个别大查询会话级临时调大 SET work_mem='256MB'
work_mem = 32MB

2.4 maintenance_work_mem

VACUUM、CREATE INDEX、ALTER TABLE 等维护操作的内存,可设较大加速这些操作。

maintenance_work_mem = 1GB

3. WAL 与检查点

详见 WAL与检查点机制,调优要点:

wal_buffers = 16MB
max_wal_size = 4GB                    # 调大→检查点更少→吞吐更好,代价是恢复更慢
min_wal_size = 1GB
checkpoint_timeout = 15min
checkpoint_completion_target = 0.9    # 几乎必调:把刷盘摊平避免IO尖峰

4. 并发连接

max_connections = 200                 # 不宜过大!每连接是一个进程,开销不小
  • PostgreSQL 每个连接是一个独立进程(不是线程),连接数过多会消耗大量内存和上下文切换。
  • 强烈建议前面加连接池(PgBouncer),而不是一味调大 max_connections。详见 连接池与连接管理
  • 经验:max_connections 控制在 100-300,通过连接池复用。

对比 MySQL:MySQL 是线程模型,单连接开销比 PG 进程模型小,所以 MySQL 能扛更多直连;PG 更依赖连接池。这也是 PG 面试常问的架构差异。

5. autovacuum

详见 VACUUM与表膨胀

autovacuum = on                       # 生产绝不关闭
autovacuum_max_workers = 4
autovacuum_vacuum_cost_limit = 2000   # 默认较保守,调大让清理更快
# 大表单独降低触发阈值:
# ALTER TABLE big SET (autovacuum_vacuum_scale_factor = 0.02);

6. 并行查询

PG 9.6+ 支持并行执行(多个 worker 并行扫描/聚合大表)。

max_worker_processes = 8
max_parallel_workers = 8
max_parallel_workers_per_gather = 4   # 单个查询最多用几个并行worker

OLAP/大表聚合场景收益明显;纯 OLTP 短查询用处不大。

7. 规划器/成本参数

random_page_cost = 1.1     # SSD 上从默认4.0调到1.1!让优化器更愿意用索引扫描
effective_io_concurrency = 200   # SSD 可调高,机械盘保持较低

random_page_cost 是 SSD 环境最值得调的参数之一:默认值 4.0 假设机械硬盘随机 IO 很贵,SSD 上应降到 1.1 左右,否则优化器可能错误地偏向全表扫描而不用索引。

8. 一个 32GB 内存 OLTP 服务器的示例配置

shared_buffers = 8GB
effective_cache_size = 24GB
work_mem = 32MB
maintenance_work_mem = 1GB
max_connections = 200
max_wal_size = 4GB
checkpoint_completion_target = 0.9
random_page_cost = 1.1
effective_io_concurrency = 200
autovacuum_vacuum_cost_limit = 2000

工具推荐:PGTune 可根据机器规格和负载类型自动生成推荐配置,作为起点很方便。

9. 面试高频问答

Q1:PostgreSQL 和 MySQL 的内存调优有什么本质区别? MySQL 靠一块大 innodb_buffer_pool(60-70% 内存);PG 的 shared_buffers 只设约 25%,其余内存交给操作系统页缓存,effective_cache_size 告知优化器总可用缓存。PG 更依赖 OS 缓存。

Q2:work_mem 设置要注意什么? 它是每操作每连接的内存,不是全局的。总消耗 ≈ work_mem × 并发 × 每查询操作数,设太大会 OOM。建议全局设小,大查询会话级临时调大。

Q3:为什么 PostgreSQL 建议用连接池? PG 每个连接是一个独立进程,连接数多则内存和切换开销大。用 PgBouncer 复用连接,把 max_connections 控制在合理范围。

Q4:SSD 环境下哪个参数最该调? random_page_cost,从默认 4.0 降到 1.1 左右,让优化器正确评估 SSD 的随机 IO 成本,避免该用索引却全表扫描。

Q5:max_wal_size 调大有什么影响? 检查点触发更少、写入吞吐更好,但崩溃恢复要重放更多 WAL、恢复时间变长,需权衡。

10. 下一步

学习 慢查询分析,定位并优化性能瓶颈。