Генератор конфигурации PostgreSQL
Контекстно-зависимые рекомендации по параметрам postgresql.conf под ваши RAM, CPU, storage и workload. Без универсальных мифов — каждое значение сопровождается диапазоном и объяснением, почему именно оно.
| Параметр | Значение | Объяснение |
|---|---|---|
| shared_buffers | 1.50 GB | Общая разделяемая память PostgreSQL для кэширования страниц данных. Классическая рекомендация — 25% RAM, но не более 8 GB на инстанс: при превышении наблюдается избыточная нагрузка на управление буферами. При 1 баз(ах) на сервере и 8 GB RAM после резерва ОС 2 GB получаем 1.50 GB. Если на сервере несколько PostgreSQL-инстансов, делите 1.50 GB между ними, а не выделяйте каждой 25%. |
| effective_cache_size | 4.50 GB | Оценка планировщиком объёма кэша ОС + shared_buffers. Не выделяет память — это просто подсказка для cost-оценки. 4.50 GB ≈ 75% от 8 GB (минус 2 GB для ОС) — реалистично для OLTP, где ОС page cache хорошо кэширует таблицы. На серверах с другими память-потребляющими сервисами снижайте до 50–60%, иначе планировщик будет ошибочно предполагать, что данные в кэше. |
| work_mem | 184 MB | Память на одну операцию сортировки/хэша, до spill на диск. 184 MB получено как (RAM − shared_buffers) / (max_connections × concurrent_factor 0.25). Concurrent_factor для Mixed = 0.25, pooler выключен (×1.0). На OLAP с большими GROUP BY даже 184 MB может быть мало — временно повышайте в сессии: SET work_mem = '256MB'; Не ставьте 184 MB глобально «с запасом»: при 100 параллельных тяжёлых запросах суммарно память превысит RAM. |
| maintenance_work_mem | 128 MB | Память для VACUUM, CREATE INDEX, ALTER TABLE. Больше — быстрее создаются индексы и проходит autovacuum на больших таблицах. 128 MB — компромисс: при 6 GB RAM, доступных PostgreSQL, это не «съест» рабочую память. На OLAP с гигантскими таблицами можно временно ставить до 4 GB на время переиндексации через ALTER SYSTEM или SET в сессии. Глобально выше 2 GB ставить бессмысленно — VACUUM не использует больше. |
| max_parallel_workers | 4 | Максимальное число фоновых worker-ов, которых PostgreSQL может запустить для параллельных сканов и индексов. Установите равным числу ядер CPU (4). На системах с другими активными сервисами — reserve 1–2 ядра. Параллелизм эффективен для OLAP-сканов больших таблиц; для OLTP его влияние обычно негативное (планировщик тратит время на coordination). |
| max_parallel_workers_per_gather | 2 | Сколько worker-ов может быть прикреплено к одному Gather-узлу. Половина от CPU (2) — стандартная рекомендация, чтобы параллельные запросы не мешали друг другу. На OLTP снижайте до 0–2, на OLAP можно поднять до 4, если запросы запускаются редко и каждый — тяжёлый. |
| max_worker_processes | 12 | Общий лимит процессов-воркеров (parallel workers, autovacuum workers, logical replication, extensions). 12 даёт запас: 4 для параллельных запросов + 8 на autovacuum (3 по умолчанию), логическую репликацию и расширения (pg_cron, pg_partman). Параметр требует restart. |
| random_page_cost | 1.1 | Стоимость случайного чтения страницы относительно последовательного. 1.1 подойдёт для SSD: на HDD случайное чтение действительно в 4× дороже, на SSD/NVMe — почти не отличается от последовательного. При 1.1 планировщик чаще выбирает index scan вместо seq scan, что критично для OLTP. Универсальный «1.1» без учёта storage — типичный миф, который может навредить на HDD. |
| effective_io_concurrency | 200 | Сколько параллельных I/O-запросов может выдать PostgreSQL. 200 для SSD — реалистичный максимум, при котором ядро Linux только успевает обрабатывать очередь. На HDD ставьте 1 — распараллеливание только вредит (поиск головки). На NVMe 1000 — базовая рекомендация PostgreSQL 14+, эффект особенно заметен на больших seq scans и VACUUM. |
| wal_buffers | 16 MB | Буфер для WAL-записей в shared memory. 16 MB — общепринятое значение: достаточно для пика WAL-записи на большинстве систем. Большие значения (> 64 MB) почти не дают прироста — Auto-tuning в PostgreSQL устанавливает 1/32 от shared_buffers, но не более 16 MB, что и является «sweet spot». Не поднимайте без замеров: это «бесплатный» по эффекту параметр. |
| checkpoint_completion_target | 0.9 | Доля времени между checkpoints, в течение которой checkpoint размазан. 0.9 — максимум полезного значения: checkpoint равномерно распределяется по 90% интервала, оставшиеся 10% — запас. Снижает пиковую I/O-нагрузку и burst-ы WAL-записей. Выше 0.9 ставить почти бессмысленно, ниже 0.7 — рискуете получить более резкие пики записи. |
| max_wal_size | 2 GB | Максимальный размер WAL между checkpoints. 2 GB — оценка для БД 50 GB: при большей БД больше WAL-генерации, нужно больше места под checkpoint. Если на диске мало места, оставьте 1 GB, но будьте готовы к частым checkpoints. Если много — поднимайте до 16 GB: меньше I/O-пиков, но дольше recovery при crash. Параметр требует reload (PostgreSQL 11+). |
| min_wal_size | 1 GB | Минимальный размер WAL, который PostgreSQL держит для переиспользования. 1 GB — стандарт: покрывает пиковую генерацию WAL на коротких всплесках без новых файловых аллокаций. Поднимайте до 2–4 GB только если наблюдаются частые «replication slot»-задержки или логическая репликация регулярно отстаёт. |
| default_statistics_target | 200 | Количество статистики, собираемой ANALYZE по каждому столбцу. 200 для Mixed: OLAP-запросы с распределёнными фильтрами и JOIN-ами требуют более детальной статистики (гистограммы по 500 bucket-ам), иначе планировщик неверно оценивает cardinality и выбирает плохой план. На OLTP 100 достаточно — короткие точечные запросы, перебор статистики только замедляет ANALYZE. На Mixed 200 — компромисс. |
| track_io_timing | on | Включает сбор таймингов I/O-операций в pg_stat_statements. Без этого нельзя понять, какие запросы страдают от медленного диска, а какие — от CPU. Параметр безопасен, overhead минимальный (менее 1% на современном железе). Обязателен для любой production-системы, где вы планируете заниматься тюнингом. |
| log_min_duration_statement | 1000 ms | Логировать все запросы дольше 1000 ms (1 секунды). Это базовый «slow query log» — критично для обнаружения деградации. 1000 ms — разумный порог: лог не заливается короткими OLTP-запросами, но ловит реально медленные аналитические. На OLAP можно поднять до 5000 ms, на OLTP — снизить до 250 ms. |
| autovacuum | on | Глобальный включатель фонового autovacuum. ON — обязательно: без него dead tuples накапливаются, таблицы разбухают, запросы замедляются, транзакции не могут повторно использовать место. На OLTP-нагрузке с частыми UPDATE/DELETE отключение autovacuum — самая частая причина аварий. Не отключайте даже на replicas (на hot standby autovacuum всё равно нужен для anti-wraparound). |
| autovacuum_naptime | 30s | Интервал между проверками autovacuum-демоном, какие таблицы нуждаются в очистке. 30s для нагрузки «Medium»: на High-нагрузке 10s позволяет оперативно убирать dead tuples и не допускать bloating, на Low — 1 мин экономит CPU. На OLTP с частыми UPDATE — снижайте до 10–30s, на OLAP с редкими изменениями — повышайте до 5–10 мин. |
| statement_timeout | 60s | Глобальный таймаут на выполнение запроса. 60s — компромисс для Mixed. На OLTP длинные запросы почти всегда — ошибка (забытый LIMIT, плохой план): 30s убивает их до того, как они повредят. На OLAP длинные аналитические запросы — норма, поэтому 0 (без ограничения). На Mixed 60s — разумная граница для аналитики, не убивая OLTP. Устанавливайте гранулярно в сессиях для аналитики. |
PostgreSQL-конфигурация — это не набор «правильных» чисел, а баланс между RAM, CPU, storage и типом нагрузки. Классические советы «shared_buffers = 25% RAM, work_mem = 64 MB, random_page_cost = 1.1» работают в среднем, но в частных случаях вредят. Например, work_mem = 64 MB для OLAP с большими GROUP BY — недостаточно: запрос уходит в temp-файл, производительность падает в 5–10 раз. А для OLTP с 1000 одновременных соединений — наоборот, 64 MB × 1000 = 64 GB, что переполнит RAM. Поэтому мы показываем диапазон и объяснение, а не фиксированное число.
shared_buffers — 25% от RAM после резерва ОС — это не догма, а разумный максимум для одного инстанса. При нескольких PostgreSQL на сервере делите 25% между ними, не давайте каждой базе по 25% — получите oversubscription. Свыше 8 GB на инстанс почти не даёт прироста: управление буферами съедает выигрыш от большего кэша. На pure-OLAP с большими seq scans shared_buffers даже можно снизить до 15–20% — OLAP меньше зависит от buffer cache, больше от effective_cache_size (OS page cache).
random_page_cost = 1.1 — рекомендация для SSD, но это миф, что «1.1 всегда правильно». На HDD random page действительно в 4× дороже sequential — планировщик должен знать это и предпочитать seq scan. Если поставить 1.1 на HDD, он начнёт генерировать index scan по большим таблицам, что убьёт производительность. Мы учитываем тип storage и подбираем соответствующее значение. Аналогично с effective_io_concurrency: на HDD ставьте 1, на NVMe — 1000.
Connection pooler (PgBouncer, pgcat) радикально меняет расчёт work_mem: вместо 100 backend-соединений у вас фактически 10–20 активных. Если pooler включён, concurrent_factor умножается на 0.4, и work_mem растёт. Без pooler — устанавливайте осторожно: умножайте work_mem на среднее число активных (не idle) соединений, не на max_connections. На большинстве production-систем 90% соединений idle — не считайте их.
Параметры, требующие restart (shared_buffers, max_worker_processes, wal_buffers), нельзя менять без планового downtime. Поэтому их стоит настраивать сразу корректно, с запасом. Параметры с reload можно итерировать на ходу. Риск «high» означает: неправильное значение критично (например, autovacuum = off почти гарантированно приведёт к аварийному bloating). Риск «medium» — заметное влияние на производительность, но recoverable. Риск «low» — настройки, которые трудно испортить (effective_cache_size, log_min_duration_statement).
Конфиг — это только начало
Загрузите audit_data.json — Express Audit покажет, как ваша текущая конфигурация реально работает на практике, и найдёт критичные проблемы с индексами, autovacuum и статистикой.