PostgreSQL с нуля: установка, настройка и честный тюнинг под корпоративную нагрузку
Я Семёнов Евгений Сергеевич, директор АйТи Фреш. За 15+ лет обслуживания корпоративных серверов у нас на практике прошли десятки развёртываний PostgreSQL — от базы 1С:ERP на производстве до 400 ГБ хранилища аналитики маркетплейса. И я видел, как одинаковый «ванильный» postgresql.conf загибается на сервере Dell с двумя Xeon Platinum 8280 и 256 ГБ памяти. База вроде поднялась, запросы идут — но вместо 2000 TPS даёт 120. В этой статье — пошаговый разбор, как установить PostgreSQL 16 на Linux, какие параметры менять и зачем, плюс реальные цифры из моих рабочих инсталляций.
Выбор версии и платформы
На момент написания актуальна PostgreSQL 16 с длительной поддержкой до ноября 2028 года. Я всегда беру последний стабильный мажор: в нём меньше багов, лучше планировщик, больше расширений. Если инфраструктура требовательна к совместимости с ПО (например, 1С требует ровно 15.x в официальной сборке), возьмите ближайший совместимый релиз.
По ОС — Ubuntu 22.04 LTS или RHEL 9 / Rocky Linux 9. Оба варианта проверены, оба работают. Windows — категорически не рекомендую даже под dev: производительность хуже на 20–30%, нет родных инструментов мониторинга, проблемы с блокировками файлов.
Установка из официального репозитория PGDG
Пакетная установка из апстримного репозитория PostgreSQL Global Development Group — единственный правильный путь. Дистрибутивный postgresql обычно отстаёт на минорный-мажорный релиз.
# Ubuntu 22.04
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
--fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
sudo sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" \
> /etc/apt/sources.list.d/pgdg.list'
sudo apt update
sudo apt install -y postgresql-16 postgresql-client-16 postgresql-contrib-16
После установки служба запустится автоматически, кластер будет в /var/lib/postgresql/16/main, конфиги — в /etc/postgresql/16/main/. Проверяем:
sudo systemctl status postgresql@16-main
sudo -u postgres psql -c "SELECT version();"
Правильная файловая структура и диски
На рабочих инсталляциях я никогда не оставляю базу в дефолтном пути на корневом диске. Стандартная схема:
| Точка монтирования | Назначение | Рекомендуемый диск | Размер |
|---|---|---|---|
| /var/lib/postgresql/16/main | Основная база (heap, индексы) | NVMe RAID10 | 2–4x размер данных |
| /var/lib/postgresql/16/wal | WAL-логи (pg_wal) | Отдельный NVMe или SSD | 100–200 ГБ |
| /backup/pg | pg_basebackup, WAL-архив | HDD RAID5/6 или NAS | 3x размер базы |
| /var/log/postgresql | Текстовые логи | Любой SSD | 20–50 ГБ |
Выделение WAL на отдельный диск даёт примерно 15–25% прироста на write-heavy нагрузках — я всегда так делаю, если сервер позволяет. Файловая система — XFS с опциями noatime,nodiratime, ext4 тоже нормально. Btrfs и ZFS — только если понимаете, зачем вам COW и сжатие (у нас один клиент на ZFS с lz4 получил экономию места 2,3x, но пришлось отключать full_page_writes в PostgreSQL).
Ключевые параметры postgresql.conf
Файл /etc/postgresql/16/main/postgresql.conf по умолчанию — для слабого ноутбука. Для продакшена его надо переписывать. Ниже — мой типовой шаблон для сервера с 64 ГБ RAM и NVMe:
# Подключения
listen_addresses = '*'
max_connections = 200
superuser_reserved_connections = 5
# Память
shared_buffers = 16GB # 25% от RAM
effective_cache_size = 48GB # ~70% от RAM (подсказка планировщику)
work_mem = 32MB # на каждую сортировку/хэш
maintenance_work_mem = 2GB # VACUUM, CREATE INDEX
wal_buffers = 64MB
huge_pages = try # включаем hugepages в ядре
# WAL и контрольные точки
wal_level = replica
max_wal_size = 8GB
min_wal_size = 2GB
checkpoint_timeout = 15min
checkpoint_completion_target = 0.9
wal_compression = on
# Параллелизм
max_worker_processes = 16
max_parallel_workers = 16
max_parallel_workers_per_gather = 4
max_parallel_maintenance_workers = 4
# Планировщик
random_page_cost = 1.1 # для NVMe/SSD
effective_io_concurrency = 200 # NVMe
default_statistics_target = 200
# Логирование
log_destination = 'csvlog'
logging_collector = on
log_directory = '/var/log/postgresql'
log_min_duration_statement = 500 # запросы > 500 мс
log_checkpoints = on
log_lock_waits = on
log_temp_files = 10MB
log_autovacuum_min_duration = 1000
# Расширения
shared_preload_libraries = 'pg_stat_statements,auto_explain'
После правки конфига — перезагрузка: sudo systemctl restart postgresql@16-main. Параметры с пометкой «reload» можно подгружать без рестарта через SELECT pg_reload_conf();.
pg_hba.conf и безопасность
Файл pg_hba.conf управляет аутентификацией. По умолчанию PostgreSQL доверяет локальным подключениям по методу peer, всем остальным — отказывает. Для корпоративной базы минимум:
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
local all all scram-sha-256
host all all 127.0.0.1/32 scram-sha-256
host all all ::1/128 scram-sha-256
host appdb appuser 10.10.0.0/16 scram-sha-256
host replication replicator 10.10.0.0/16 scram-sha-256
# Остальное явно запрещено — default deny
Пароли — только scram-sha-256, MD5 уже давно считается слабым. В конфиге password_encryption = scram-sha-256. При создании пользователя:
CREATE ROLE appuser LOGIN PASSWORD 'СтойкийПароль123!' VALID UNTIL '2027-01-01';
CREATE DATABASE appdb OWNER appuser ENCODING 'UTF8' LC_COLLATE 'ru_RU.UTF-8' LC_CTYPE 'ru_RU.UTF-8';
Мониторинг через pg_stat_statements и Prometheus
Без pg_stat_statements вы слепой. Это расширение ведёт накопленную статистику по всем запросам: количество вызовов, общее время, среднее время, чтения с диска, попадания в кэш. Включается в shared_preload_libraries + CREATE EXTENSION pg_stat_statements;. Топ-10 медленных запросов:
SELECT substring(query, 1, 80) AS query,
calls, total_exec_time::int AS total_ms,
mean_exec_time::int AS avg_ms, rows
FROM pg_stat_statements
ORDER BY total_exec_time DESC LIMIT 10;
Для графиков — Prometheus postgres_exporter + Grafana dashboard 9628. Собирает 200+ метрик: транзакции, блокировки, bloat, репликация. У нас на практике один клиент (интернет-магазин на 1С-Битрикс, база 180 ГБ) благодаря этим графикам нашёл запрос, который раз в 10 минут сканил всю таблицу orders. После добавления индекса load average на сервере упал с 18 до 3.
Мини-кейс: база 1С:ERP на 120 пользователей
В феврале 2026 взяли в обслуживание производственный холдинг — 120 пользователей 1С:ERP, база 340 ГБ, старый HP ProLiant DL380 Gen9 с 128 ГБ RAM и HDD RAID10. Жалобы: закрытие месяца идёт 14 часов, ERP «висит» каждый день около 11 утра. Что сделали:
- Пересобрали сервер на Dell PowerEdge R750 с двумя Xeon Platinum 8280, 256 ГБ RAM, NVMe RAID10 4x3,2 ТБ, сетевая Mellanox 40G до СХД резервного копирования.
- Развернули PostgreSQL 15 (версия под 1С), shared_buffers 64 ГБ, work_mem 48 МБ, effective_cache_size 192 ГБ.
- Включили pg_stat_statements, нашли 6 топовых запросов — добавили 11 индексов, 3 запроса переписали с LATERAL JOIN.
- Настроили autovacuum под нагрузку (scale_factor 0.05 на горячих таблицах).
- Потоковая репликация на резерв в дата-центр МТС с задержкой менее секунды.
Результат: закрытие месяца за 2 часа 20 минут (было 14), средний отклик интерфейса 1С упал с 1,8 до 0,3 секунды, «зависаний» больше нет. Стоимость проекта — 280 тыс. руб. за работы плюс новое железо.
Бэкап, репликация и обслуживание
Правило: если у вас нет резервной копии за сегодня — у вас нет резервной копии вообще. Минимальный стек:
- pg_basebackup раз в сутки — полная копия кластера, архивируется на NAS.
- WAL-архив через
archive_command— точка восстановления с точностью до секунды за последние 7 суток. - Потоковая репликация на standby-сервер — синхронная или асинхронная, зависит от требований.
- pgBackRest — если нужен инкремент и сжатие. Освоить раз, пользоваться всегда.
# archive_command в postgresql.conf
archive_mode = on
archive_command = 'test ! -f /backup/wal/%f && cp %p /backup/wal/%f'
wal_keep_size = 16GB
# Запуск базовой копии
sudo -u postgres pg_basebackup -D /backup/base/$(date +%Y%m%d) \
-Ft -z -P -R -X stream
Обязательно раз в квартал тестируйте восстановление из бэкапа на отдельной машине. База, которую невозможно поднять — не база.
Настроим PostgreSQL под вашу нагрузку
Подниму PostgreSQL 16 на вашем сервере, настрою репликацию, бэкапы и мониторинг. Аудит текущего инстанса с рекомендациями по тюнингу — за один день, полная миграция с MS SQL или Oracle — от двух недель. Базы от 20 ГБ до нескольких ТБ.
Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш
FAQ — частые вопросы по PostgreSQL
- Сколько памяти выделять под shared_buffers?
- Стандартная рекомендация — 25% от RAM сервера. На машине с 64 ГБ ставим 16 ГБ, остальное оставляем под дисковый кэш ОС. Больше 40% не имеет смысла — PostgreSQL использует двойное кэширование через page cache Linux.
- Какой work_mem выставить?
- work_mem задаётся на каждую операцию сортировки/хэша. Для OLTP начните с 16–32 МБ, для аналитики можно 128–256 МБ. Если max_connections=200 и work_mem=64MB, в пике получите до 12,8 ГБ RAM на одни только сортировки.
- Нужно ли отключать autovacuum?
- Никогда. Отключённый autovacuum за месяц превращает базу в распухший неработоспособный файл. Тюньте параметры — autovacuum_vacuum_scale_factor, autovacuum_naptime — но не отключайте.
- Какую файловую систему выбрать для PostgreSQL?
- XFS или ext4 с опцией noatime. ZFS даёт сжатие и снапшоты, но требует аккуратной настройки recordsize=8K и отключения двойного кэширования. На продакшене под большие нагрузки я выбираю XFS на NVMe.
- Как замерить реальную нагрузку на PostgreSQL?
- Включите pg_stat_statements, настройте Prometheus postgres_exporter + Grafana dashboard. Смотрите top-10 запросов по total_time, метрики blks_hit/blks_read, размер базы и длину очереди на бэкенд.