11 KiB
PostgreSQL 4 核 16G 生产调参基线
更新时间:2026-06-30
这份文档用于后续把 Supabase/PostgreSQL 自托管到 4 核 16G 云服务器时做生产起步配置。目标是先给题库 SaaS 一个安全、可回滚、可观测的基线,而不是追求一次性压满硬件。
参考来源:
- postgresqlco.nf Tuning Guide:https://postgresqlco.nf/tuning-guide
- PostgreSQL 官方 Resource Consumption:https://www.postgresql.org/docs/current/runtime-config-resource.html
- PostgreSQL 官方 Query Planning:https://www.postgresql.org/docs/current/runtime-config-query.html
- PostgreSQL 官方 WAL/Checkpoint:https://www.postgresql.org/docs/current/runtime-config-wal.html
- PostgreSQL 官方 Connections:https://www.postgresql.org/docs/current/runtime-config-connection.html
说明:postgresqlco.nf 的页面可作为参数分类和调参入口参考;具体参数语义、重启要求和风险以 PostgreSQL 官方文档为准。
适用前提
- 单台 4 vCPU、16 GB RAM 云服务器。
- 同机可能运行 Supabase 服务、API、worker、Nginx、日志/监控 agent。
- 数据库以题库读多写少、后台批量导入、支付/订单小事务、学习记录持续写入为主。
- 生产必须使用 SSD 云盘,数据库数据盘和备份盘分开更好。
如果 PostgreSQL 是唯一重负载服务,可以使用下方 dedicated-db 值;如果 API/worker/Nginx 也在同机,先使用 shared-host 值。
推荐起步值
| 参数 | shared-host 起步值 | dedicated-db 起步值 | 说明 |
|---|---|---|---|
max_connections |
80 |
120 |
4 核机器不宜靠大量直连抗并发;API 侧连接池和 Supabase pooler 更重要 |
shared_buffers |
3GB |
4GB |
官方建议专用库可从约 25% RAM 起步;同机多服务要给 OS cache 和应用留空间 |
effective_cache_size |
10GB |
12GB |
这是优化器估算值,不实际占内存 |
work_mem |
16MB |
16MB |
每个排序/哈希操作都可能分配一次,不按连接数简单相乘 |
maintenance_work_mem |
512MB |
768MB |
导入、建索引、VACUUM 可受益;注意 autovacuum worker 并发 |
autovacuum_work_mem |
256MB |
256MB |
避免多个 autovacuum 同时吃掉过多内存 |
wal_buffers |
16MB |
16MB |
默认自动通常够用;16MB 是常见稳妥上限 |
min_wal_size |
1GB |
2GB |
给批量导入和写入波峰预留 WAL |
max_wal_size |
6GB |
8GB |
减少频繁 checkpoint;值越大,崩溃恢复时间可能更长 |
checkpoint_timeout |
10min |
15min |
降低 checkpoint 频率;配合 max_wal_size 观察恢复窗口 |
checkpoint_completion_target |
0.9 |
0.9 |
平滑 checkpoint I/O |
effective_io_concurrency |
100 |
100 |
SSD 云盘起步值;机械盘不适用 |
random_page_cost |
1.1 |
1.1 |
SSD 上鼓励合理索引扫描;上线后用 EXPLAIN 复核 |
jit |
off |
off |
题库 API 多为短查询,先避免 JIT 带来的计划开销 |
log_min_duration_statement |
500ms |
500ms |
上线初期捕捉慢 SQL;稳定后可调到 1000ms |
idle_in_transaction_session_timeout |
60s |
60s |
防止后台或脚本长事务占锁 |
statement_timeout |
30s |
30s |
API 请求不应长期占用数据库;导入脚本用会话级覆盖 |
lock_timeout |
5s |
5s |
防止普通请求长时间等锁 |
证据采集脚本
仓库已补上线前证据采集脚本:
npm run perf:postgres:evidence
脚本会输出 JSON/Markdown 到已忽略的 docs/refactor/launch-artifacts/,包含:
pg_settings中关键调参项、来源和pending_restart。pg_stat_activity连接状态、锁等待和 I/O 等待聚合。pg_stat_database事务、回滚和缓存命中率。pg_stat_bgwritercheckpoint 计数和耗时。- public schema 大表估算行数、总大小和索引大小。
- 如已启用
pg_stat_statements,输出按总执行耗时排序的 Top SQL。
上云后建议顺序是:先采集一次默认值,应用本文件 shared-host 参数并重启需要重启的项,再采集一次,然后跑 API 阶梯压测。调参证据和压测报告一起进入本地 production-launch-evidence.json,不要提交真实证据文件。
应用连接池边界
4 核机器的关键不是把 max_connections 拉大,而是控制同时活跃 SQL 的数量。
建议:
apps/api主进程连接池:DB_POOL_MAX=10到20。apps/worker每类 worker 连接池:DB_POOL_MAX=4到8。- 导入、导出、对账、公共题库同步等 worker 不要全部高并发同时跑。
- H5/Taro 前端永远不直连数据库,只走 Supabase Auth 或
apps/api。 - 生产如使用 Supabase pooler,应限制事务池大小,避免 API 扩容后数据库连接被打满。
ALTER SYSTEM 示例
上线前先保存当前值:
select name, setting, unit, source, pending_restart
from pg_settings
where name in (
'max_connections',
'shared_buffers',
'effective_cache_size',
'work_mem',
'maintenance_work_mem',
'autovacuum_work_mem',
'wal_buffers',
'min_wal_size',
'max_wal_size',
'checkpoint_timeout',
'checkpoint_completion_target',
'effective_io_concurrency',
'random_page_cost',
'jit',
'log_min_duration_statement',
'idle_in_transaction_session_timeout',
'statement_timeout',
'lock_timeout'
)
order by name;
同机部署推荐先执行:
alter system set max_connections = '80';
alter system set shared_buffers = '3GB';
alter system set effective_cache_size = '10GB';
alter system set work_mem = '16MB';
alter system set maintenance_work_mem = '512MB';
alter system set autovacuum_work_mem = '256MB';
alter system set wal_buffers = '16MB';
alter system set min_wal_size = '1GB';
alter system set max_wal_size = '6GB';
alter system set checkpoint_timeout = '10min';
alter system set checkpoint_completion_target = '0.9';
alter system set effective_io_concurrency = '100';
alter system set random_page_cost = '1.1';
alter system set jit = 'off';
alter system set log_min_duration_statement = '500ms';
alter system set idle_in_transaction_session_timeout = '60s';
alter system set statement_timeout = '30s';
alter system set lock_timeout = '5s';
select pg_reload_conf();
以下参数需要重启 PostgreSQL 才会生效:max_connections、shared_buffers、wal_buffers。执行后用下面语句确认:
select name, setting, unit, pending_restart
from pg_settings
where pending_restart = true
order by name;
导入脚本会话级覆盖
真实迁移导入、批量导入、建索引可能超过普通 API 的 statement_timeout。不要为了导入放大生产全局超时,应该在导入连接上局部设置:
set statement_timeout = '30min';
set lock_timeout = '30s';
set maintenance_work_mem = '1GB';
正式切换仍以 pb:import:dry-run --profile=production、pb:import:json、pb:import:validate 和业务抽样为准。
观察和验收
上线后至少观察 24 到 72 小时:
select state, wait_event_type, wait_event, count(*)::int
from pg_stat_activity
where datname = current_database()
group by state, wait_event_type, wait_event
order by count desc;
select datname, xact_commit, xact_rollback, blks_read, blks_hit,
round(blks_hit * 100.0 / nullif(blks_hit + blks_read, 0), 2) as cache_hit_ratio
from pg_stat_database
where datname = current_database();
select checkpoints_timed, checkpoints_req, checkpoint_write_time, checkpoint_sync_time
from pg_stat_bgwriter;
select pid, usename, now() - xact_start as xact_age, state, query
from pg_stat_activity
where xact_start is not null
order by xact_age desc
limit 20;
验收标准:
- API P95 延迟稳定,没有大量
ClientRead/ClientWrite、锁等待或 I/O wait。 pb:import:validate无 failure。checkpoints_req不应持续快速增长;如增长明显,优先调大max_wal_size或检查写入峰值。- 没有 OOM、没有频繁连接耗尽、没有长时间 idle in transaction。
- 慢 SQL 日志能对应到具体接口、worker 或迁移脚本。
pg_stat_statements
上线压测和灰度期间建议启用 pg_stat_statements。如果自托管 Supabase/PostgreSQL 允许修改 shared_preload_libraries,推荐:
alter system set shared_preload_libraries = 'pg_stat_statements';
该参数需要重启 PostgreSQL。重启后执行:
create extension if not exists pg_stat_statements;
select pg_stat_statements_reset();
每轮压测后看总耗时、平均耗时和调用量最高的 SQL,再决定是否新增索引、改 SQL、加预聚合或调整 API 缓存。不要把慢 SQL 明细直接提交到 Git,因为其中可能包含业务表名、常量和内部路径。
压测闭环
调参后必须跑 API 压测,不要只凭参数表判断容量。当前仓库提供本地压测脚本:
npm run perf:api:local
默认压测只读路径,会自动发现真实迁移后的租户、学生、题库入口、合集、蓝图、单词和手册数据,并输出报告到已忽略的 docs/refactor/performance-reports/。详细环境变量、4 核 16G 阶梯并发矩阵和报告归档方式见:
docs/refactor/performance-benchmark-runbook.md
4 核 16G 首次上云建议至少跑:
smoke:6 并发 30 秒,只读。baseline-30:30 并发 5 分钟,只读。baseline-50:50 并发 5 分钟,只读。mixed-30:30 并发 5 分钟,开启少量练习 session 写入。
若 P95/P99 明显升高,优先结合慢 SQL、pg_stat_activity 和报告中的接口明细定位,再考虑索引、预聚合、连接池和 worker 调度;不要直接继续放大 max_connections。
回滚方式
如果调参后出现内存压力、启动失败或查询计划异常:
alter system reset shared_buffers;
alter system reset effective_cache_size;
alter system reset work_mem;
alter system reset maintenance_work_mem;
alter system reset autovacuum_work_mem;
alter system reset wal_buffers;
alter system reset min_wal_size;
alter system reset max_wal_size;
alter system reset checkpoint_timeout;
alter system reset checkpoint_completion_target;
alter system reset effective_io_concurrency;
alter system reset random_page_cost;
alter system reset jit;
alter system reset log_min_duration_statement;
alter system reset idle_in_transaction_session_timeout;
alter system reset statement_timeout;
alter system reset lock_timeout;
select pg_reload_conf();
若 shared_buffers、wal_buffers、max_connections 已改,需要重启后才算完全回滚。
后续优化方向
- 上线后启用
pg_stat_statements,按总耗时和平均耗时定位慢 SQL。 - 为
answer_records、practice_sessions、content_asset_access_events、video_play_events等大表规划按月或按租户分区。 - 对租户后台 dashboard、排行榜、销售转化、分佣报表做日/小时预聚合。
- 对真实
pb:import:json增加阶段耗时统计,继续批量化questions/question_versions。 - 如果三套 H5、API、worker、Supabase 全部同机,优先加连接池和 worker 调度,而不是继续放大 PostgreSQL 内存参数。