VK Cloud

Масштабирование базы данных: когда БД перестаёт справляться с ростом нагрузки

4 августа 2026 г.
шпрингер.png
Елена Шпрингер
Автор статьи
_blog_head_45.png

Приложение запускалось на одном сервере и держало 1000 пользователей без единой жалобы. На 50 000 активных пользователей страницы стали открываться с задержкой, отчёты крутились по десять секунд. На 200 000 активных пользователей база данных превратилась в узкое место всей системы: код оптимизирован, кэш прогрет, а запросы всё равно упираются в один и тот же сервер СУБД.

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

Сначала рассмотрим признаки того, что база данных работает на пределе. Затем — стратегии масштабирования: от самых простых (например, оптимизации запросов) до более сложных (например, шардирования). Эта статья для тех, кто чувствует проблему на уровне метрик и жалоб, но не всегда знает, каким термином она называется: для разработчиков, архитекторов и CTO на стадии активного роста.

shirkova2_85c1a19cd1.jpeg

Статья подготовлена вместе с экспертами

Дарья Шибкова, менеджер продукта

ковальчук2.jpg

Дмитрий Ковальчук, менеджер продукта

Как понять, что база данных перестает справляться с нагрузкой

База данных редко перестает справляться с нагрузкой мгновенно. Сначала растёт задержка на пиках, потом деградация становится постоянной. Ловить момент нужно по метрикам, а не по жалобам пользователей: к моменту, когда жалобы дошли до поддержки, база уже перегружена. Ниже перечислены пороги, которые стоит держать под алертами постоянно.

Метрики, которые нужно мониторить постоянно

Используйте таблицу как ориентир-светофор: зелёная зона — норма, жёлтая — пора планировать масштабирование, красная — база данных уже стала узким местом.

Метрика 🟢 Зелёный 🟡 Жёлтый 🔴 Красный Что означает
CPU (sustained) < 50% 50–70% > 70% Высокая загрузка CPU увеличивает время выполнения запросов и время ожидания в очереди. 
Buffer cache hit ratio > 99% 95–99% < 95% Данные читаются с диска, а не из RAM. Возможные причины: недостаточный объём RAM, неэффективные индексы или неоптимальные запросы
Disk I/O await (SSD) < 10 мс 10–20 мс > 20 мс Диск не успевает за нагрузкой ввода-вывода
Connections < 60% max 60–80% max > 80% max Приближается исчерпание доступных соединений (connection storm), свободных подключений почти не осталось 
Replication lag < 100 мс 0,1–1 с > 1–5 с Реплика отстаёт, поэтому чтение с неё может возвращать устаревшие данные
Slow queries нет > 1 с единичные > 1 с регулярные > 1 с Запросы выполняются дольше ожидаемого

Порог устойчивой загрузки CPU (sustained) выше 70% — инженерный ориентир, а не жесткая граница: конкретное значение зависит от профиля нагрузки и запаса под пики. Аналогично, пороги по disk I/O await и количеству соединений в таблице служат практическими ориентирами, а не абсолютными константами.

Buffer cache hit ratio отражает процент страниц, извлекаемых из оперативной памяти (buffer cache) без обращения к диску. Для систем OLTP значение ниже 95% обычно сигнализирует о дефиците горячих данных в RAM или о неэффективном использовании индексов (последовательное сканирование). Для оценки метрики необходимо выполнить запрос к системной статистике:

SELECT sum(heap_blks_hit) / sum(heap_blks_hit + heap_blks_read) FROM pg_statio_user_tables;

Connections выше 80% от max_connections — предвестник connection storm, когда всплеск клиентов разом занимает все свободные слоты, и новые подключения начинают падать с ошибкой. Replication lag в норме держится ниже 100 мс, но под нагрузкой даёт всплески вплоть до минут.

Симптомы на уровне продукта

Инженер видит проблему в метриках, а бизнес — в деградации пользовательского опыта. Timeout в час пик, когда каталог не открывается под нагрузкой. Пользователи замечают, что страницы каталога, поиска и отчётов начинают открываться значительно медленнее, сложные SELECT с JOIN начинают стоить секунды. Медленный поиск и фильтрация: запросы перебирают миллионы строк без индекса. Отчёты формируются несколько минут и начинают конкурировать с транзакционной нагрузкой за ресурсы. Очереди на запись, когда блокировки строк выстраивают транзакции в цепочку. Ключевым системным индикатором перегрузки является регулярная необходимость в «тушении пожаров»: если DBA или дежурный инженер вынужден еженедельно вручную прерывать зависшие запросы, перезапускать пулы и чистить блокировки, это свидетельствует о том, что база данных работает на пределе своих возможностей. В такой ситуации система находится в состоянии хронической нестабильности, хотя полный отказ еще не наступил.

Антипаттерн: почему простое увеличение объёма RAM не решает проблему

При первых признаках деградации производительности обычно увеличивают объём памяти и число CPU. Это разумная тактическая мера: вертикальное масштабирование (scale-up) позволяет быстро снизить нагрузку на сервер, устранить узкое место и выиграть время для дальнейшего анализа. Однако такой подход эффективен лишь до определённого предела. Но как стратегия оно не работает: когда объём горячих данных превышает RAM, тюнинг shared_buffers уже не помогает: оптимальный диапазон составляет около 25% от объема RAM с практическим максимумом в 8–16 ГБ. Данные, превышающие этот лимит, неизбежно будут считываться с диска, что делает дальнейший рост параметра бессмысленным для производительности. Дальше упор идёт в потолок железа и в стоимость: каждый следующий шаг по мощности сервера дорожает нелинейно. Момент, когда докидывание RAM перестаёт помогать, сигналит, что база данных не справляется с нагрузкой архитектурно, и пора переходить к стратегиям масштабирования.

Стратегии масштабирования: от простого к сложному

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

Уровень 0: оптимизация запросов и индексов

Самый дешёвый и самый недооценённый уровень. Правильный индекс ускоряет запрос в 10–100 раз, и часто одного этого достаточно, чтобы снять нагрузку без единого нового сервера. Типовые проблемы: отсутствие индексов на колонках в WHERE и JOIN, проблема N+1 (когда приложение вместо одного запроса делает по одному на каждую строку списка), SELECT * вместо перечисления нужных колонок, отсутствие партицирования на больших таблицах. Низкий buffer cache hit ratio часто указывает именно сюда: последовательное сканирование без индекса гоняет с диска страницы, которых там быть не должно.

Инструменты диагностики: EXPLAIN ANALYZE показывает реальный план выполнения запроса, slow query log собирает всё, что дольше порога, расширение pg_stat_statements агрегирует статистику по всем запросам и находит самые дорогие. Начинать масштабирование, не пройдя этот уровень, почти всегда преждевременно.

Уровень 1: вертикальное масштабирование (scale-up)

Наращивание ресурсов одного сервера: больше CPU, больше RAM, быстрые NVMe-диски. Главный плюс в простоте: приложение не меняется, схема данных не трогается, риск минимален. Это первый этап масштабирования: сначала выжимают максимум из вертикального масштабирования, затем переходят к горизонтальному. Несмотря на простоту внедрения, вертикальное масштабирование ограничено физическими пределами. Когда объем данных выходит за рамки оптимального размера RAM, оптимизация памяти теряет смысл, а стоимость оборудования растет быстрее, чем увеличивается производительность системы.

Уровень 2: read replicas

В большинстве веб-приложений 80–95% запросов приходится на чтение: карточки товаров, ленты, поиск, профили. Read replica (реплика для чтения): копия мастера, которая принимает на себя SELECT-запросы, пока мастер занимается записью. Реплики оправданы, когда доля чтения достигает примерно 80% трафика: тогда вынос чтения разгружает мастер в разы, а добавление новых реплик почти линейно наращивает пропускную способность на чтение.

Плата за это: асинхронность. Данные доезжают до реплики с задержкой (replication lag), и сразу после записи клиент может прочитать с реплики устаревшую версию. Типичный сценарий: пользователь оставил комментарий, страница перезагрузилась с реплики, а комментария ещё нет. Для таких случаев применяют паттерн read-your-writes: чтение только что записанных данных направляют на мастер, остальное на реплики. Мониторинг lag при этом обязателен: реплика, отставшая на минуты, тихо отдаёт неверные ответы.

Уровень 3: connection pooling

PostgreSQL создаёт под каждое клиентское соединение отдельный процесс операционной системы, и каждый такой процесс стоит около 5–10 МБ RAM даже в простое; тысяча соединений на сервере с 8 ГБ памяти съедает её впустую. Connection pooling (пул соединений) решает это посредником: PgBouncer держит тысячи клиентских подключений, но к самой БД открывает лишь десятки, переиспользуя их между клиентами. Для продакшена с более чем сотней одновременных соединений пул обязателен, а не опционален.

В режиме transaction pooling PgBouncer переиспользует бэкенд-соединения между транзакциями, а не держит их закреплёнными за клиентом на всю сессию: это и даёт основной прирост эффективной ёмкости при том же числе реальных подключений к БД. Размер бэкенд-пула подбирают по классическому ориентиру (ядра × 2) + число дисков. Пул отвязывает жизненный цикл клиента от дорогого бэкенд-процесса, и один этот слой часто снимает проблему, которую иначе списали бы на нехватку памяти.

Уровень 4: шардирование

Горизонтальное разбиение данных по нескольким серверам: каждый шард: самостоятельная СУБД, которая хранит своё подмножество данных, а маршрутизация идёт по ключу шардирования (например, по user_id). Теоретически масштабируется неограниченно, включая запись. Практически: самая дорогая мера с серьёзной платой за сложность: JOIN между шардами работает только по колонке распределения (co-located данные), а произвольный JOIN между шардами недоступен или дорог; транзакция, затрагивающая несколько шардов, требует двухфазного коммита (2PC); приложение приходится переписывать под топологию шардов.

Для PostgreSQL шардирование чаще всего строят на расширении Citus: оно раскладывает таблицы по узлам через distribution column и держит связанные строки на одном узле (co-location), чтобы JOIN между ними работал локально; JOIN между шардами возможен только по общей колонке распределения, а справочные reference-таблицы синхронизируются через 2PC. Шардирование: последняя мера, к которой переходят, только исчерпав все предыдущие уровни.

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

Этап Стратегия Сложность Когда применять
1 Оптимизация запросов и индексов Низкая Всегда первым, до любого железа
2 Вертикальное масштабирование Низкая Быстрый прирост, пока есть потолок
3 Connection pooling Низкая Более 100 одновременных соединений
4 Read replicas Средняя Read-heavy нагрузка (≥ 80% чтения)
5 Кэширование Redis Средняя Повторяющиеся дорогие запросы
6 Партицирование Средняя Таблицы от 100 млн строк
7 Шардирование Высокая Предыдущие уровни исчерпаны

Специфика масштабирования разных типов БД

Стратегии универсальны, но потолки и инструменты у СУБД разные. То, что в одной базе решается штатной фичей, в другой требует внешнего расширения.

PostgreSQL: сильные стороны и ограничения

Универсальная реляционная СУБД для OLTP-нагрузки (обработки транзакций в реальном времени). Хорошо масштабируется вертикально и через read replicas. Горизонтальное шардирование в ядре отсутствует и решается через Citus или FDW; актуальный релиз на момент публикации: PostgreSQL 18. Главное ограничение: пропускная способность на запись упирается в один мастер. Read replicas разгружают только чтение: при write-heavy нагрузке они не помогают, и это тот случай, когда приходится смотреть в сторону других семейств или шардирования.

MySQL / MariaDB: Group Replication и Galera

Здесь запись можно масштабировать на несколько узлов, чего нет в single-master модели PostgreSQL. Group Replication: мультимастер-репликация с согласованием на основе кворума большинства (majority-consensus): узлы договариваются о порядке транзакций голосованием. Galera Cluster: синхронная мультимастер-репликация, где транзакция подтверждается сразу на всех узлах. Оба подхода дают несколько точек записи и потому подходят для геораспределённой записи, где нельзя гонять все транзакции через один мастер. Плата: накладные расходы на согласование между узлами и чувствительность к сетевым задержкам.

NoSQL как дополнение к реляционной БД

Часто правильный ход: не масштабировать основную реляционную БД до бесконечности, а снять с неё непрофильную нагрузку. Redis берёт на себя кэш и сессии, разгружая PostgreSQL от повторяющихся SELECT. ClickHouse забирает аналитику: тяжёлые агрегирующие запросы убивают OLTP-базу, а колоночная СУБД справляется с ними на другом порядке объёмов. Elasticsearch или OpenSearch закрывают полнотекстовый поиск по каталогу, который в реляционной базе всегда дорог. Подробнее о связке управляемых баз под высоконагруженный сценарий: в материале «E-commerce и DBaaS: масштабируемые решения для ритейла».

Управляемые базы данных VK Cloud снимают операционную часть масштабирования, когда держать DBA в штате дорого или некогда: read replicas, connection pooling и автоматический failover на резервную реплику работают на уровне сервиса. Масштабирование чтения и переключение при сбое мастера настраиваются через панель, а не скриптами на своих серверах. Попробовать DBaaS →

Облако как инфраструктура масштабирования: преимущества и ограничения

Облако не отменяет законы масштабирования, но убирает ручной труд на каждом уровне. Операции, которые в self-hosted занимают часы настройки, в управляемом сервисе сводятся к нескольким кликам. Важно понимать границу: где облако реально помогает, а где остаётся ответственность архитектора.

Что даёт облачная СУБД при масштабировании

Введение облачной СУБД меняет природу масштабирования: вместо трудоемкого проекта оно становится операцией, которая работает через панель управления. Read replica добавляется в несколько кликов вместо ручной настройки репликации. Вертикальное масштабирование делается через resize с минимальным даунтаймом, а не миграцией на новый сервер. Connection pooling и failover работают на стороне провайдера.

VK Cloud DBaaS поддерживает управляемые инстансы MySQL, PostgreSQL, MongoDB, Redis, ClickHouse, Tarantool и OpenSearch. Для разных СУБД доступны конфигурации Single, Master-Replica и Cluster; в зависимости от выбранной топологии сервис берет на себя значительную часть задач администрирования, включая развертывание, управление репликацией, резервное копирование и восстановление.

Для PostgreSQL кластерная конфигурация поддерживает синхронную и асинхронную репликацию, балансировщик нагрузки и автоматическое переключение роли master при недоступности основного узла. Высокая доступность PostgreSQL-кластера обеспечивается службой Patroni: после failover одна из реплик становится новым master, а сервис создает замену выбывшей реплике.

Мультизональная конфигурация повышает устойчивость к отказам инфраструктуры: узлы кластера распределяются между зонами доступности, поэтому выход из строя одного ЦОД не обязательно приводит к недоступности базы. При сохранении кворума кластер автоматически выбирает новый master и продолжает принимать транзакции; такая схема особенно полезна для высоконагруженных систем и сервисов с высокими требованиями к сохранности данных.

Connection pooling устраняет необходимость самостоятельно разворачивать и сопровождать отдельный PgBouncer или аналогичный компонент. Пул соединений ограничивает число прямых подключений к СУБД, снижает накладные расходы на создание сессий, помогает переживать кратковременные всплески запросов и защищает базу от исчерпания доступных подключений. Управление через интерфейс сервиса упрощает настройку и делает поведение подключений более предсказуемым для прикладных команд.

Автомасштабирование ресурсов по заданным порогам позволяет заранее определить реакцию на рост нагрузки — например, на увеличение потребления CPU, памяти или свободного места на диске. Это снижает риск инцидентов из-за нехватки ресурсов, уменьшает объем ручных операций со стороны DBA и DevOps и позволяет не держать постоянно избыточную конфигурацию на всякий случай.

Подробнее о возможностях DBaaS VK Cloud →

Когда облачный DBaaS не заменяет архитектурных решений

Честный взгляд: облако остаётся инструментом, а не подменяет проектирование. Проблема производительности в коде будет актуальной и в managed-базе: провайдер не переписывает запросы приложения. Неправильно спроектированная схема данных не станет быстрее от миграции: денормализация, отсутствие нужных индексов, гигантские таблицы без партицирования переезжают в облако вместе с приложением. DBaaS снимает операционную нагрузку (бэкапы, failover, обновления, мониторинг + вертикальное и горизонтальное масштабирование, автомасштабирование дисков ), но не делает работу архитектора.

Сравнение подходов к масштабированию

Параметр Self-hosted VK Cloud DBaaS
Добавить read replica Ручная настройка, 1–8 ч Несколько кликов
Вертикальное масштабирование Миграция + даунтайм Resize, минимальный даунтайм
Горизонтальное масштабирование  Проектирование и настройка шардинга, балансировки и межузлового взаимодействия вручную  Масштабирование через read replicas, для шардинга требуется отдельная архитектура 
Автомасштабирование диска Кастомный скрипт Встроено
Connection pooler Отдельная установка PgBouncer Встроено
Failover Вручную через Patroni Автоматический
Мониторинг метрик Prometheus + Grafana вручную Встроенные дашборды
Стоимость DevOps Высокая, DBA в штате Снижена

Практический чек-лист: что сделать до того, как БД встанет

Масштабирование дешевле готовить заранее, чем чинить под нагрузкой. Ниже — минимум, который стоит закрыть, пока метрики в зелёной зоне.

Чек-лист готовности к росту нагрузки

✅ Мониторинг выстроен. CPU, RAM, IOPS, connections, replication lag и slow queries шлют алерты до того, как войдут в красную зону, а не после.

✅ Индексы проверены. Нет отсутствующих индексов на горячих WHERE/JOIN и нет неиспользуемых, которые зря тормозят запись.

✅ Connection pooling настроен. PgBouncer стоит перед базой, если одновременных соединений больше сотни.

✅ Read replica добавлена. Чтение уходит на реплику, мастер занят записью; паттерн read-your-writes продуман для критичных сценариев.

✅ Кэширование внедрено. Redis прикрывает повторяющиеся тяжёлые SELECT.

✅ Тест нагрузки пройден. Точка деградации известна заранее — вы знаете, на каком RPS база начнёт захлёбываться.

✅ Резервное копирование настроено и восстановление проверено. Бэкап без проверенного восстановления не считается бэкапом.

Заключение

Проблемы масштабирования нарастают постепенно, и это не плохая новость: между первым жёлтым сигналом на дашборде и реальным отказом обычно есть недели, а то и месяцы. Успеет среагировать тот, у кого выстроен мониторинг, кто знает стратегии в правильном порядке и подготовил инфраструктуру заранее.

На практике оптимизация запросов, read replicas и connection pooling закрывают около 80% случаев, когда база данных перестаёт справляться, и делают это дёшево. Шардирование нужно редко и остаётся крайней мерой для по-настоящему больших объёмов. Переход на управляемый VK Cloud DBaaS снимает операционную нагрузку и ускоряет те же самые шаги масштабирования базы данных, но не отменяет работу над схемой и запросами. Порядок действий важнее героизма: сначала измерить, потом применять стратегии снизу вверх.

Частые вопросы про масштабирование базы данных

Что делать, если база данных тормозит?

Начните с диагностики запросов, а не с покупки железа. Включите slow query log, прогоните тяжёлые запросы через EXPLAIN ANALYZE: правильный индекс ускоряет запрос в 10–100 раз и часто снимает проблему целиком. Только после этого смотрите на метрики CPU, RAM, IOPS и connections, и лишь затем переходите к масштабированию инфраструктуры.

Когда нужно шардирование базы данных?

Шардирование: последняя мера. Сначала пройдите оптимизацию запросов, вертикальное масштабирование, read replicas, connection pooling и кэширование. К шардированию переходят при объёмах данных от нескольких терабайт или нагрузке от сотен тысяч запросов в секунду, когда все предыдущие уровни исчерпаны, из-за высокой сложности (ограничения на JOIN между шардами, двухфазные транзакции, переписывание приложения).

В чём разница между вертикальным и горизонтальным масштабированием БД?

Вертикальное масштабирование: наращивание ресурсов одного сервера (CPU, RAM, диски); оно простое, но ограничено потолком железа. Горизонтальное масштабирование: добавление новых серверов в виде реплик или шардов; оно сложнее в реализации, но теоретически неограниченно по ёмкости. На практике сначала выжимают выжимают максимум из вертикального масштабирования, затем переходят к горизонтальному

Что такое read replica и как она помогает при масштабировании?

Read replica: копия базы-мастера, которая обслуживает только запросы на чтение. Поскольку в большинстве приложений 80–95% запросов приходится на SELECT, вынос чтения на реплики разгружает мастер, оставляя ему запись. Каждая добавленная реплика почти линейно умножает пропускную способность на чтение; плата — асинхронная задержка (replication lag), которую нужно учитывать для сценариев, где важна свежесть данных.

Оставьте заявку, чтобы получить консультацию

Наши специалисты свяжутся с вами в ближайшее время и ответят на все вопросы.

section_subscribe_2x_9ab2d878a6.png

            Узнавайте о выходе новых статей в блоге первыми!

            Будем держать в курсе новостей и облачных трендов

            section-subscribe_2x.png
              section-subscribe_2x.png
              Теги: postgresql, базы данных, VK Cloud, облако
              Ссылка скопирована
              Поделиться

              Почитать по теме

              _blog_head_140.png
              27 июля

              Надёжность БД: что помогает избежать потери данных

              _blog_head_32.png
              22 июля

              ПАК для корпоративного ИИ: железо и мультиагентная платформа в одной поставке

              40+ готовых сервисов