PostgreSQL настройка памяти: Оптимизация shared_buffers, work_mem, maintenance_work_mem | AdminWiki

PostgreSQL настройка памяти: Полное руководство по оптимизации для DevOps

19 декабря 2025 8 мин. чтения #devops #postgresql #postgresql конфигурация #базы данных #настройка памяти #оптимизация #производительность

Введение: Почему настройка памяти PostgreSQL критически важна

Представь, что твой PostgreSQL-сервер — это большой офис. Память — это рабочие столы сотрудников (оперативная память), а диск — это архив в подвале. Если рабочие столы слишком маленькие, сотрудники постоянно бегают в архив за документами, и работа замедляется. Если столы слишком большие — офис пустует, а деньги на аренду (оперативку) тратятся впустую. Давай разберем, как правильно "обставить" наш офис, чтобы PostgreSQL работал на максимум.

Ключевая мысль: Правильная настройка памяти PostgreSQL — это баланс между использованием оперативной памяти для быстрого доступа к данным и предотвращением излишнего потребления, которое может привести к свопингу и деградации производительности всей системы.

Основные параметры памяти в PostgreSQL

PostgreSQL управляет памятью через несколько ключевых параметров в файле postgresql.conf. Давай рассмотрим каждый из них, как опытный DevOps инженер.

shared_buffers — самый важный параметр

Это кэш PostgreSQL, где хранятся часто используемые страницы данных с диска. Представь его как главный рабочий стол в нашем офисе-аналогии.

postgresql.conf
# Рекомендуемое значение: 25% от общей оперативной памяти
# Для сервера с 16 ГБ RAM:
shared_buffers = 4GB

# Для сервера с 64 ГБ RAM:
shared_buffers = 16GB
Внимание! Не устанавливай shared_buffers больше 40% от доступной памяти на Linux. Системе и другим процессам тоже нужна оперативка. На Windows лимит обычно около 512 МБ-1 ГБ из-за архитектурных ограничений.

work_mem — память для операций сортировки и хеширования

Эта память выделяется для каждой операции сортировки (ORDER BY, DISTINCT) или хеш-соединения. Каждый запрос может использовать work_mem несколько раз, если в нем несколько операций сортировки.

postgresql.conf
# Базовый расчет: (общая RAM - shared_buffers) / max_connections / 2
# Для сервера 16 ГБ RAM, 100 соединений:
work_mem = 64MB  # (16GB - 4GB) / 100 / 2 ≈ 64MB

# Для сервера с большими аналитическими запросами:
work_mem = 256MB

maintenance_work_mem — память для служебных операций

Используется для операций обслуживания: VACUUM, CREATE INDEX, REINDEX, CLUSTER. Можно устанавливать значительно больше, чем work_mem.

postgresql.conf
# Рекомендуется: 5-10% от общей оперативной памяти
# Для сервера 16 ГБ RAM:
maintenance_work_mem = 1GB

# Для сервера 64 ГБ RAM:
maintenance_work_mem = 4GB

effective_cache_size — "оптимизационная" память

Это не реальное выделение памяти, а подсказка планировщику запросов о том, сколько кэша доступно в системе (включая кэш ОС). Влияет на выбор плана выполнения запросов.

postgresql.conf
# Устанавливается примерно в 50-75% от общей оперативной памяти
# Для сервера 16 ГБ RAM:
effective_cache_size = 12GB

# Для сервера 64 ГБ RAM:
effective_cache_size = 48GB

Пошаговое руководство по настройке памяти PostgreSQL

Шаг 1: Анализ текущей конфигурации

Сначала посмотрим, что у нас сейчас настроено:

SQL запрос
-- Показать текущие настройки памяти
SELECT name, setting, unit, context, vartype
FROM pg_settings 
WHERE name IN (
    'shared_buffers', 
    'work_mem', 
    'maintenance_work_mem', 
    'effective_cache_size',
    'max_connections'
)
ORDER BY name;

Шаг 2: Расчет оптимальных значений для вашего сервера

Используй эту таблицу как шпаргалку для расчета:

Параметр Формула расчета Пример для 16 ГБ RAM Пример для 64 ГБ RAM
shared_buffers 25% от RAM 4 GB 16 GB
work_mem (RAM - shared_buffers) / max_connections / 2 64 MB (при 100 соединениях) 256 MB (при 100 соединениях)
maintenance_work_mem 5-10% от RAM 1 GB 4 GB
effective_cache_size 50-75% от RAM 12 GB 48 GB

Шаг 3: Применение настроек

Отредактируй файл postgresql.conf:

postgresql.conf
# Memory Configuration
shared_buffers = 4GB           # 25% от 16GB RAM
work_mem = 64MB                # (16GB - 4GB) / 100 / 2
maintenance_work_mem = 1GB     # ~6% от 16GB RAM
effective_cache_size = 12GB    # 75% от 16GB RAM

# Не забудь про эти важные параметры:
max_connections = 100          # Оптимально для большинства приложений
wal_buffers = 16MB             # Обычно 1/32 от shared_buffers, но не менее 64KB и не более 16MB

Шаг 4: Перезагрузка и проверка

bash
# Перезагружаем конфигурацию PostgreSQL
sudo systemctl reload postgresql
# ИЛИ для применения некоторых изменений может потребоваться рестарт
sudo systemctl restart postgresql

# Проверяем, что настройки применились
psql -U postgres -c "SELECT name, setting FROM pg_settings WHERE name LIKE '%mem%' OR name LIKE '%buffer%' ORDER BY name;"

Мониторинг использования памяти

После настройки важно отслеживать, как PostgreSQL использует память. Вот полезные запросы:

SQL запросы для мониторинга
-- Кэш-попадания в shared_buffers
SELECT 
    sum(heap_blks_read) as heap_read,
    sum(heap_blks_hit)  as heap_hit,
    (sum(heap_blks_hit) - sum(heap_blks_read)) / sum(heap_blks_hit) as ratio
FROM pg_statio_user_tables;

-- Использование памяти процессами PostgreSQL
SELECT 
    pid,
    usename,
    application_name,
    state,
    pg_size_pretty(pg_total_relation_size(relid)) as relation_size,
    query 
FROM pg_stat_activity 
WHERE state = 'active' 
ORDER BY query_start DESC;

-- Общее использование shared_buffers
SELECT 
    pg_size_pretty(count(*) * 8192) as shared_buffers_used
FROM pg_buffercache;

Продвинутые техники настройки

Настройка для OLTP и OLAP нагрузок

Разные типы нагрузок требуют разных подходов:

  • OLTP (Online Transaction Processing): Много коротких запросов, высокая конкуренция за память. Устанавливай меньший work_mem (32-64MB) и больше уделяй внимания shared_buffers.
  • OLAP (Online Analytical Processing): Сложные аналитические запросы с сортировками и агрегациями. Увеличивай work_mem (256MB-1GB) и maintenance_work_mem для быстрого создания индексов.

Huge Pages для Linux

Для больших инсталляций PostgreSQL (более 32 ГБ RAM) используй Huge Pages для снижения накладных расходов на управление памятью:

bash
# В /etc/sysctl.conf добавляем:
vm.nr_hugepages = 1024  # Количество huge pages (2MB каждая)

# В postgresql.conf:
huge_pages = on  # или try для автоматического отката при недостатке памяти

Часто задаваемые вопросы (FAQ)

Как проверить, не слишком ли большой work_mem?

Если work_mem слишком большой, PostgreSQL может начать использовать своп. Проверяй с помощью:

bash
# Мониторинг использования swap
free -h
vmstat 1  # Смотри колонку 'si' и 'so' (swap in/out)

# В PostgreSQL смотри количество временных файлов:
SELECT datname, temp_files, temp_bytes FROM pg_stat_database;

PostgreSQL использует всю доступную память, это нормально?

Да, это нормально и даже правильно! PostgreSQL старается максимально использовать доступную оперативную память для кэширования данных. Проблема возникает только если начинается активный своппинг или не хватает памяти другим критическим процессам.

Как настроить память для контейнеризованного PostgreSQL?

В контейнерах важно учитывать лимиты памяти, установленные Docker/Kubernetes:

docker-compose.yml
services:
  postgres:
    image: postgres:15
    environment:
      POSTGRES_SHARED_BUFFERS: 1GB
      POSTGRES_EFFECTIVE_CACHE_SIZE: 3GB
      POSTGRES_WORK_MEM: 32MB
    deploy:
      resources:
        limits:
          memory: 4G  # Общий лимит контейнера
Совет: В Kubernetes используй Vertical Pod Autoscaler для автоматической настройки памяти PostgreSQL на основе фактического использования.

Заключение

Настройка памяти PostgreSQL — это не разовая операция, а непрерывный процесс оптимизации. Начни с базовых рекомендаций из этой статьи, затем мониторь производительность и корректируй параметры под конкретную нагрузку твоего приложения. Помни, что идеальных настроек "на все случаи жизни" не существует — каждый сервер уникален.

Ключевые принципы, которые ты должен запомнить:

  • Баланс: Не отдавай всю память PostgreSQL, оставь ресурсы для ОС и файлового кэша
  • Мониторинг: Регулярно проверяй cache hit ratio и использование временных файлов
  • Постепенность: Меняй настройки по одной и отслеживай эффект
  • Контекст: Учитывай тип нагрузки (OLTP vs OLAP) и специфику приложения
Финальный совет: Перед любыми изменениями в production-окружении обязательно тестируй на staging-сервере с похожей нагрузкой. Используй pgbench для нагрузочного тестирования и сравнения производительности до и после изменений.
Поделиться:
Сохранить гайд? В закладки браузера