docs: update launch capacity and postgres tuning

This commit is contained in:
Codex
2026-07-01 05:15:31 +08:00
parent 1eb5a13df7
commit c73722202e
8 changed files with 131 additions and 22 deletions

View File

@@ -131,6 +131,45 @@ export const postgresTuningProfiles = {
type: 'duration',
rationale: 'Ordinary API requests should not wait a long time behind locks.',
},
temp_file_limit: {
recommended: '4GB',
min: '1GB',
max: '8GB',
type: 'bytes',
rationale: 'Bound accidental large sorts/hash spills from reports or imports on a shared host.',
},
log_temp_files: {
recommended: '128MB',
min: '64MB',
max: '512MB',
type: 'bytes',
rationale: 'Log large temp-file spills during launch without logging every tiny sort.',
},
log_checkpoints: {
recommended: 'on',
exact: 'on',
type: 'text',
rationale: 'Checkpoint logs help correlate latency spikes with WAL/checkpoint pressure.',
},
track_io_timing: {
recommended: 'on',
exact: 'on',
type: 'text',
rationale: 'Required to diagnose read/write I/O time for real-data benchmark bottlenecks.',
},
track_wal_io_timing: {
recommended: 'on',
exact: 'on',
type: 'text',
rationale: 'Required to diagnose WAL fsync/write pressure during answer/order/import writes.',
},
max_parallel_workers_per_gather: {
recommended: '1',
min: 0,
max: 2,
type: 'number',
rationale: 'Keep OLTP API requests from consuming too many workers per query on 4 vCPU.',
},
},
},
'dedicated-db': {
@@ -156,6 +195,12 @@ export const postgresTuningProfiles = {
idle_in_transaction_session_timeout: { recommended: '60s', min: '30s', max: '120s', type: 'duration' },
statement_timeout: { recommended: '30s', min: '5s', max: '60s', type: 'duration' },
lock_timeout: { recommended: '5s', min: '1s', max: '10s', type: 'duration' },
temp_file_limit: { recommended: '8GB', min: '2GB', max: '12GB', type: 'bytes' },
log_temp_files: { recommended: '128MB', min: '64MB', max: '512MB', type: 'bytes' },
log_checkpoints: { recommended: 'on', exact: 'on', type: 'text' },
track_io_timing: { recommended: 'on', exact: 'on', type: 'text' },
track_wal_io_timing: { recommended: 'on', exact: 'on', type: 'text' },
max_parallel_workers_per_gather: { recommended: '2', min: 0, max: 2, type: 'number' },
},
},
};

View File

@@ -25,11 +25,15 @@ assert.equal(sharedSql.status, 0, sharedSql.stderr);
assert.match(sharedSql.stdout, /alter system set shared_buffers = '3GB';/);
assert.match(sharedSql.stdout, /alter system set statement_timeout = '30s';/);
assert.match(sharedSql.stdout, /alter system set jit = 'off';/);
assert.match(sharedSql.stdout, /alter system set track_io_timing = 'on';/);
assert.match(sharedSql.stdout, /alter system set track_wal_io_timing = 'on';/);
assert.match(sharedSql.stdout, /alter system set temp_file_limit = '4GB';/);
const dedicatedSql = run(['--print-sql', '--profile=dedicated-db']);
assert.equal(dedicatedSql.status, 0, dedicatedSql.stderr);
assert.match(dedicatedSql.stdout, /alter system set shared_buffers = '4GB';/);
assert.match(dedicatedSql.stdout, /alter system set max_wal_size = '8GB';/);
assert.match(dedicatedSql.stdout, /alter system set temp_file_limit = '8GB';/);
const invalidProfile = run(['--print-sql', '--profile=unknown']);
assert.notEqual(invalidProfile.status, 0, 'unknown profile should fail');

View File

@@ -217,6 +217,9 @@ function evaluateProfile(settingsRows, profile) {
if (actual !== String(rule.exact).toLowerCase()) {
failures.push(`${name} should be ${rule.exact} for ${profile.label}, got ${setting.setting}.`);
}
if (String(setting.source || '').toLowerCase() === 'default') {
warnings.push(`${name} still comes from default; recommended ${profile.name} value is ${rule.recommended}.`);
}
continue;
}
if (rule.min !== undefined) {