Capacity planning: CPU, RAM, IOPS, соединения и рост данных

↑ Этап 7 · Эксплуатация и безопасность БД

По желанию~5 мин чтенияУровень: middle+

Зачем это на собесе

Планирование ёмкости предотвращает аварии «закончилось место/соединения» и помогает обосновать бюджет.

Зачем

Ответить заранее на вопросы: когда закончится диск? Выдержит ли БД рост нагрузки вдвое? Сколько ресурсов нужно под пик? Когда пора масштабироваться?

Метод: измерить текущее → смоделировать рост → добавить запас → договориться о пороге действий → проверить нагрузочными тестами.

Ресурсы

CPU

Определяется сложностью запросов и числом одновременно активных сессий. Ориентир для OLTP: активных соединений не более cores × 2..4; больше — очереди и переключение контекста. Метрики: загрузка, load average, steal (в облаке), доля ожидания I/O. Параллельные запросы используют несколько ядер (max_parallel_workers).

Память (RAM)

ПараметрРоль
shared_buffers~25% RAM
Кэш ОСостальная память: «горячие» данные должны помещаться (working set)
work_memна каждую операцию сортировки/хэша каждого запроса: work_mem × операций × соединений
maintenance_work_memVACUUM, индексы
Память процессов~5–10 МБ на соединение + кэши

Цель: рабочий набор данных и индексов помещается в память (cache hit > 99%). Признаки нехватки: рост blks_read, сортировки на диск, swap, OOM killer.

Диск (объём и IOPS)

  • Объём: данные + индексы + bloat + WAL + временные файлы + бэкапы/архив WAL + запас на VACUUM FULL/перестроение индексов (до 2× таблицы);
  • IOPS и пропускная способность: случайные чтения (индексы), запись WAL (последовательная), checkpoint;
  • Задержка (latency): критична для fsync WAL (коммиты);
  • типы: NVMe/SSD для OLTP; отдельные тома для WAL и данных (опционально);
  • облако: лимиты IOPS/throughput тома (gp3, io2), «burst credits» (исчерпание приводит к падению производительности).
SELECT pg_size_pretty(pg_database_size('app')) AS db,
       pg_size_pretty(sum(pg_total_relation_size(c.oid))) AS tables_and_indexes
FROM pg_class c WHERE c.relkind IN ('r','m','t');
 
SELECT relname, pg_size_pretty(pg_total_relation_size(oid)) AS total,
       pg_size_pretty(pg_relation_size(oid)) AS heap, pg_size_pretty(pg_indexes_size(oid)) AS idx
FROM pg_class WHERE relkind = 'r' ORDER BY pg_total_relation_size(oid) DESC LIMIT 10;

Соединения

max_connections (по умолчанию 100) и реальное число клиентов (сервисы × размер пула). Формула для размера пула приложения: pool_size ≈ (cores × 2) + effective_spindle_count для одной БД суммарно; а не «максимум на всякий случай». Используйте PgBouncer; мониторьте numbackends / max_connections, очереди ожидания пула (cl_waiting).

Сеть

Пропускная способность и задержка (репликация, бэкапы, большие выборки), межзональный трафик.

Рост данных и прогноз

  1. Собрать историю: размер БД и таблиц раз в сутки (таблица db_size_history, Prometheus pg_database_size_bytes).
  2. Определить тренд: линейный (predict_linear в Prometheus) или экспоненциальный; учесть сезонность (распродажи, отчётные периоды).
  3. Драйверы роста: число пользователей, событий, заказов → объём на единицу бизнес-метрики (например, 2 КБ на заказ × 100k заказов в месяц = 200 МБ/мес + индексы ×2).
  4. Прогноз: через 6/12/24 месяцев.
  5. Порог действий: «при 70% диска — расширяем; при 85% — авария».
predict_linear(node_filesystem_avail_bytes{mountpoint="/var/lib/postgresql"}[7d], 30 * 24 * 3600) < 0

Контроль роста: партиционирование и удаление старых данных, архивация (S3, ClickHouse), TTL, сжатие (TOAST, lz4), очистка bloat, удаление неиспользуемых индексов.

Пик нагрузки и запас

  • проектируйте под пиковые значения (p95/p99 недели/месяца), не под средние;
  • запас (headroom): CPU 30–40%, диск 30%, память; до 70% нормальной загрузки;
  • N+1 отказоустойчивость: при потере узла оставшиеся выдерживают нагрузку;
  • разовые события (маркетинг, релиз, миграция, бэкап, отчёты) учитывайте отдельно.

Нагрузочное тестирование

  • pgbench (стандартные и свои сценарии), k6, JMeter, Gatling, воспроизведение реального трафика (pgreplay, pg_stat_statements);
  • тесты на данных продового размера и распределения;
  • измеряйте: TPS, p95/p99 latency, CPU, iowait, hit ratio, лаг репликации, при растущей нагрузке — точку насыщения;
  • сценарии: пик, долгая устойчивая нагрузка (soak), скачок (spike), отказ узла (chaos).
pgbench -i -s 1000 app                   # инициализация, масштаб 1000 (≈15 ГБ)
pgbench -c 64 -j 8 -T 600 -P 10 app      # 64 клиента, 8 потоков, 10 минут

Способы масштабирования

СпособКогдаКомментарий
Оптимизация запросов и индексоввсегда первымдешевле любого железа
Вертикальное (scale up)быстро, простопредел и цена, возможен простой
Read replicasвысокая доля чтениялаг, маршрутизация
Кэш (Redis), CQRSповторяющиеся чтенияинвалидация
Пул соединениймного клиентовPgBouncer
Партиционирование, архивациябольшие таблицы
Аналитика вынести (ClickHouse)тяжёлые отчётыCDC
Шардированиезапись и объём за пределами одного узласложность

Стоимость (FinOps)

Тип инстанса, диски и IOPS, реплики, бэкапы и хранение, межзональный трафик, лицензии. Правила: удалить неиспользуемое, архивировать, резервировать мощности (reserved/savings plans) для стабильных нагрузок, автоскейлинг реплик (где поддерживается), отдельные контуры dev/stage меньшего размера.

Процесс

  • ежемесячный/ежеквартальный обзор ёмкости (capacity review) с отчётом: текущее использование, прогноз, риски, рекомендации;
  • дашборд ёмкости и алерты по прогнозу;
  • привязка к бизнес-планам (запуск новых функций, рост пользователей);
  • документ «пределы системы»: известные узкие места и порог перехода на следующую архитектуру.

Вопросы с ответами