Для первоначальной настройки PostgresSQL мы берем из официальной документации
В этой статье я напишу мои рекомендации по оптимизации
Настройки PostgreSQL
Настройки будут производиться через ALTER SYSTEM
Параллельные операции
ALTER SYSTEM SET parallel_setup_cost = '500'; -- Стоимость запуска параллельных процессов
ALTER SYSTEM SET cpu_operator_cost = '0.0025'; -- Стоимость CPU для операций (+, -, *)
ALTER SYSTEM SET cpu_tuple_cost = '0.01'; -- Стоимость обработки строки CPU
Эффект: Уменьшение parallel_setup_cost делает параллельные запросы более привлекательными для планировщика. Остальные параметры оставлены по умолчанию.
Autovacuum Оптимизация
ALTER SYSTEM SET autovacuum_work_mem = '1GB'; -- Память на процесс autovacuum
ALTER SYSTEM SET autovacuum_naptime = '30s'; -- Пауза между проверками
ALTER SYSTEM SET autovacuum_vacuum_cost_limit = '4000'; -- Лимит работы за цикл
ALTER SYSTEM SET autovacuum_vacuum_cost_delay = '2ms'; -- Задержка при лимите
- Для чего:
- Ускорение autovacuum за счет увеличения памяти (
work_mem) и агрессивности (cost_limitв 20 раз выше дефолта) - Частые проверки (
naptime=30sвместо 60s) - Минимизация простоев (
cost_delay=2msвместо 20ms)
- Ускорение autovacuum за счет увеличения памяти (
Пороги срабатывания Autovacuum
ALTER SYSTEM SET autovacuum_vacuum_scale_factor = '0.05'; -- 5% изменённых строк
ALTER SYSTEM SET autovacuum_analyze_scale_factor = '0.05'; -- 5% для анализа
ALTER SYSTEM SET autovacuum_vacuum_threshold = '10000'; -- Мин. число мёртвых строк
ALTER SYSTEM SET autovacuum_analyze_threshold = '500'; -- Мин. изменений для ANALYZE
- Логика:
- VACUUM запустится при:
>10к мертвых строкИЛИ>5% мертвых строк - ANALYZE запустится при:
>500 измененийИЛИ>5% изменений - Важно: Для больших таблиц уменьшение
scale_factorкритично (5% от 1 млрд = 50 млн — много!)
- VACUUM запустится при:
Надёжность и WAL
ALTER SYSTEM SET synchronous_commit = 'on'; -- Гарантия записи WAL на диск
ALTER SYSTEM SET wal_compression = 'zstd'; -- Сжатие WAL (lz4/zstd лучше)
ALTER SYSTEM SET full_page_writes = 'on'; -- Защита от порчи данных при сбое
ALTER SYSTEM SET wal_keep_size = '1GB'; -- Минимальный размер WAL для реплик
- Зачем:
- Безопасность данных (
synchronous_commit,full_page_writes) - Экономия места на диске (
wal_compression) - Обеспечение работы реплик/бэкапов (
wal_keep_size)
- Безопасность данных (
Мониторинг
ALTER SYSTEM SET log_autovacuum_min_duration = '2s'; -- Логирование медленных autovacuum
Помогает выявлять проблемы с длительными операциями обслуживания.
Проверка параметров
SELECT name, setting FROM pg_settings WHERE name LIKE '%autovac%';
Вывод: Все параметры autovacuum с их текущими значениями (удобно для аудита)
Оптимизация ОС: Ядро Linux
Конфигурация (/etc/sysctl.conf)
Раздел VM (Virtual Memory)
vm.dirty_background_ratio = 0
Отключает процентный расчет фоновых «грязных» страниц. Используется вместе с dirty_background_bytes.
vm.dirty_ratio = 0
Отключает процентный расчет для основных «грязных» страниц. Используется с dirty_bytes.
vm.dirty_background_bytes = 104857600
Максимальный объем «грязных» страниц (незаписанных данных), при котором фоновые процессы начинают асинхронную запись на диск.
Зачем: Предотвращает лавинообразную запись при заполнении буфера.
vm.dirty_bytes = 1073741824
Максимальный объем «грязных» страниц, при котором приложения блокируются для синхронной записи на диск.
Для PostgreSQL: Защищает от длительных блокировок при внезапной нагрузке.
vm.dirty_expire_centisecs = 300
Время, после которого «грязные» данные обязаны быть записаны на диск.
Эффект: Гарантирует, что данные не задерживаются в памяти слишком долго.
vm.dirty_writeback_centisecs = 100
Частота активации процессов записи «грязных» страниц на диск.
Оптимизация: Более частые, но мелкие операции записи вместо больших пиков.
vm.overcommit_memory=2
0: Разрешать overcommit (с риском OOM-Killer)2: Запрещать выделение памяти, если нет гарантий ее доступности
Для БД: Защита от внезапной смерти процесса PostgreSQL при нехватке памяти.
vm.overcommit_ratio=100
Процент RAM + SWAP, разрешенный для выделения при overcommit_memory=2.100% = RAM + весь SWAP.
vm.swappiness = 1
Агрессивное избегание использования swap:
0: полное отключение свопа (не рекомендуется)1: минимально возможное использование
Для PostgreSQL: Предотвращает деградацию производительности при своппинге.
Раздел Kernel
kernel.numa_balancing = 0
Отключает автоматический баланс памяти между узлами NUMA.
Зачем: Для СУБД ручное управление через numactl часто эффективнее.
kernel.sched_autogroup_enabled = 0
Отключает автоматическую группировку задач по сессиям.
Для PostgreSQL: Предотвращает несправедливое распределение CPU между фоновыми процессами и основными запросами.
Далле идут три параметра которые требуют тонкой настройки под конкретную нагрузку
kernel.sched_migration_cost_ns = 50000000
Время, после которого задача считается «кешированной»
kernel.sched_nr_migrate = 2
Макс. задач для миграции между CPU
kernel.sched_min_granularity_ns = 100000000
Минимальное время выполнения задачи
Раздел Network
Отключение IPv6:
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
Упрощение сетевого стека, если используется только IPv4.
Буферы TCP:
net.core.rmem_max = 1073741824
Макс. размер буфера приёма (1 GB)
net.core.wmem_max = 1073741824
Макс. размер буфера отправки (1 GB)
net.ipv4.tcp_rmem = 1048576 16777216 1073741824
Min, default, max для приёма
net.ipv4.tcp_wmem = 1048576 16777216 1073741824
Min, default, max для отправки
Для PostgreSQL: Улучшает производительность при:
- Множестве параллельных подключений
- Передаче больших результатов запросов
- Репликации
Таймауты TCP
net.ipv4.tcp_fin_timeout = 30
Время ожидания FIN-пакета (сек)
net.ipv4.tcp_keepalive_intvl = 30
Интервал между keepalive-пакетами (сек)
Быстрее освобождает соединения в состоянии TIME_WAIT.
net.ipv4.tcp_reordering = 20
Увеличивает порог переупорядочивания пакетов.
Зачем: Снижает ложные ретрасмиты в сетях с высокой вариативностью задержек.
net.ipv4.tcp_mem = 1048576 16770216 1073741824
Управление памятью для TCP:
- Min (4096 страниц × 4KB = 16MB)
- Pressure (≈65MB)
- Max (1GB)
Для применения настроек необходимо выполнить
sudo sysctl -p
Huge Pages: Ускорение работы с памятью
Зачем использовать Huge Pages?
- Уменьшение накладных расходов TLB
- TLB (Translation Lookaside Buffer) — кэш процессора для трансляции виртуальных адресов в физические.
- Стандартные страницы (4KB): TLB покрывает малый объём памяти → частые промахи → замедление работы.
- Huge Pages (1GB/2MB): Одна запись TLB покрывает гигабайт памяти → меньше промахов → ускорение операций с памятью.
- Снижение нагрузки на ядро ОС
- Меньше структур данных для управления памятью (1 запись для 1GB вместо 262,144 записей для 4KB-страниц).
- Уменьшение contention на спин-блокировках ядра.
- Ускорение инициализации shared_buffers
- PostgreSQL при запуске выделяет
shared_buffers. С Huge Pages это происходит в 100-1000 раз быстрее.
- PostgreSQL при запуске выделяет
Эффект для PostgreSQL:
- До +30% к скорости OLTP-нагрузки при больших
shared_buffers(особенно > 64GB). - Стабильность производительности при интенсивной работе с памятью.
Как включить Huge Pages (1GB) в Debian
Шаг 1: Проверить поддержку CPU
grep pdpe1gb /proc/cpuinfo | uniq
Если есть вывод — процессор поддерживает 1GB-страницы.
Шаг 2: Добавить параметры ядра
Отредактировать /etc/default/grub:
GRUB_CMDLINE_LINUX="... hugepagesz=1G hugepages=16 default_hugepagesz=1G"
hugepagesz=1G— размер страницы.hugepages=16— количество страниц (16 × 1GB = 16GB памяти).default_hugepagesz=1G— размер по умолчанию.
Обновить конфигурацию GRUB:
update-grub
Перезагрузить сервер:
reboot
Шаг 3: Проверить выделение памяти
grep HugePages_ /proc/meminfo
Ожидаемый вывод:
HugePages_Total: 16
HugePages_Free: 16
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 1048576 kB # 1GB
Шаг 4: Настроить PostgreSQL
ALTER SYSTEM SET huge_pages = "on";
ALTER SYSTEM SET huge_page_size = "1GB";
Важно! Установить vm.nr_overcommit_hugepages (если PostgreSQL не может выделить память):
sysctl -w vm.nr_overcommit_hugepages=32 # Резерв страниц
Когда НЕ использовать Huge Pages?
- Маленькие БД (
shared_buffers < 8GB). - Системы с нехваткой RAM (память резервируется заранее).
- Контейнеризованные среды (cgroups могут блокировать доступ).