После знакомства с разными базами возникает главный вопрос: что выбрать для своей задачи? Универсально лучшего хранилища нет. Одна база быстро читает документ целиком, другая соединяет таблицы, третья ищет по тексту, четвертая агрегирует миллиарды событий. Поэтому выбирают не технологию по известности, а модель данных и гарантии под конкретные запросы.
Сравнительная таблица
| Хранилище | Тип данных | Когда выбирать | Когда не выбирать |
|---|---|---|---|
| PostgreSQL | Таблицы, строки, jsonb | Основная база приложения, заказы, платежи, связи, JOIN, транзакции, отчеты среднего размера | Огромный поток событий без обновлений, файлы целиком, специализированный поисковый или аналитический контур |
| MongoDB | Документы | Объект читается целиком, структура документов меняется, вложенные атрибуты, каталог с разными типами товаров | Много связей и соединений, строгая целостность между сущностями, сложные транзакции по всей системе |
| Redis | Ключ-значение и структуры в памяти | Кэш, сессии, счетчики, короткие очереди, блокировки, рейтинги, быстрый доступ по известному ключу | Единственное хранилище критичных данных без продуманной долговечности, произвольные запросы по содержимому |
| Elasticsearch | Поисковый индекс документов | Полнотекстовый поиск, релевантность, опечатки, фасеты, поисковые подсказки, логи | Основная база заказов и платежей, строгие транзакции, запись как единственный источник истины |
| ClickHouse | Колонки и большие наборы событий | Аналитика, витрины, агрегаты по миллионам и миллиардам строк, метрики, события, OLAP | Частые точечные обновления, короткие транзакции, чтение одной карточки по всем колонкам |
| Cassandra | Широкие строки по ключу раздела | Очень большой поток записи, события и телеметрия, предсказуемые запросы, работа в нескольких регионах | Произвольные запросы, JOIN, аналитика, транзакции между строками, неизвестная заранее модель чтения |
| Neo4j | Узлы и связи графа | Многошаговые обходы, рекомендации, антифрод, социальные связи, граф знаний, GraphRAG | Простые сущности без важных связей, обычные фильтры и агрегаты, где хватает реляционных таблиц |
| S3 и object storage | Файлы и объекты | Изображения, видео, архивы, резервные копии, выгрузки, Parquet и озеро данных | Запросы к отдельным полям записи, транзакции, быстрые обновления одной строки |
Таблица не отвечает, какая база лучше. Она помогает отбросить явно неподходящие варианты. Финальный выбор делают по реальным запросам и нагрузке.
Ориентиры по TPS и объему
TPS здесь означает операции в секунду: чтение по простому ключу или простая запись. Диапазоны нужны только для первой прикидки класса решения. Это не предельные характеристики и не обещание производительности.
Допущения: современный сервер с SSD или небольшой кластер, короткие операции, индексы под запросы, пакетная запись там, где она допустима. Сложный JOIN, большой документ, строгая согласованность или синхронная репликация уменьшают эти числа на порядки.
| Хранилище | Чтение, TPS | Запись, TPS | Рабочий объем |
|---|---|---|---|
| PostgreSQL | 10 000-100 000 точечных | 1 000-10 000 транзакций | Сотни ГБ - несколько ТБ на узел |
| MongoDB | 10 000-100 000 документов | 1 000-10 000 документов | Сотни ГБ - десятки ТБ |
| Redis | 50 000-500 000 операций | 50 000-500 000 операций | Десятки - сотни ГБ оперативной памяти |
| Elasticsearch | 100-5 000 поисковых запросов | 5 000-50 000 документов на индексацию | Сотни ГБ - десятки ТБ индексов |
| ClickHouse | 10-1 000 аналитических запросов | 50 000-1 000 000 строк пакетами | ТБ - сотни ТБ событий |
| Cassandra | 1 000-50 000 партиций | 5 000-100 000 строк | ТБ - сотни ТБ на кластер |
| Neo4j | 100-5 000 обходов | 100-5 000 транзакций | Десятки ГБ - несколько ТБ графа |
| S3 и object storage | 100-5 000 объектов | 100-5 000 объектов | От КБ до ТБ на объект, общий объем практически не ограничен |
Числа нельзя сравнивать как скорость автомобилей. Аналитический запрос ClickHouse сканирует миллионы строк, обход Neo4j проходит переменное число связей, а чтение Redis возвращает маленькое значение по ключу. Поэтому сначала выбирают модель операции, а диапазон используют как проверку реалистичности.
Механизмы масштабирования по размеру
| Размер и нагрузка | Что применять в первую очередь |
|---|---|
| Горячие данные помещаются в память | Индексы, пул соединений, компактные ответы, кэш повторных чтений в Redis |
| Сотни ГБ, чтение по известным ключам | Составные и покрывающие индексы, разделение горячих и холодных данных, реплики чтения |
| Тысячи записей в секунду | Пакетная запись, меньше индексов на запись, быстрые диски, очередь перед базой для сглаживания пиков |
| ТБ истории | Партиционирование по времени или ключу, срок хранения, агрегаты, доставка истории в ClickHouse |
| Десятки ТБ и больше | Шардинг по осмысленному ключу, отдельный аналитический контур, object storage для сырых данных |
| Десятки тысяч записей непрерывно | Пакеты и очереди, Cassandra при предсказуемых чтениях по ключу раздела, ClickHouse для аналитического потока |
| Большие файлы | S3 плюс CDN, в базе только метаданные и ссылка на объект |
Это не жесткие пороги. Сотня ГБ с плохим запросом может быть проблемой раньше, чем десять ТБ хорошо партиционированных событий. Смотрят на рабочий набор, а не только на общий размер базы.
Как посчитать требуемый TPS
Формула для первой оценки:
Требуемый TPS = средний TPS в час пик × коэффициент пиковой нагрузки × запас на рост и сбои
Обычно берут пик в 5-10 раз выше среднего и запас 1,5-2 раза. Например, в час пик приложение читает 200 операций в секунду, а пишет 40:
Чтение: 200 × 8 × 2 = 3 200 TPS
Запись: 40 × 5 × 2 = 400 TPS
Одна PostgreSQL с подходящими индексами вполне кандидат на такой профиль. Но решение подтверждают нагрузочным тестом: смотрят не только TPS, а задержку p95 и p99, ошибки, память, диск и длину очереди. Если при этом чтение упирается в повторы, добавляют кэш. Если запись растет быстрее одного узла, сначала оптимизируют пакеты и индексы, а уже потом шардируют.
Пример объема: 80 ТБ фотографий
Есть 50 млн карточек, по 4 фотографии размером 400 КБ:
50 000 000 × 4 × 400 КБ = 80 000 000 000 КБ ≈ 80 ТБ
Байты изображений держат в S3, в PostgreSQL оставляют идентификатор товара, адрес объекта, порядок снимка и технические метаданные. Для раздачи ставят CDN, иначе 20 000 запросов изображений в секунду превратятся в дорогой поток через приложение и хранилище. Если часть снимков удаляется или меняется, отдельно проектируют очистку старых объектов и ссылку в базе.
Алгоритм выбора
1. Выписать главные операции
Возьмите пять самых частых чтений и три самые важные записи. Не «пользователь работает с заказами», а конкретно:
- найти заказ по номеру со всеми позициями;
- показать последние двадцать заказов покупателя;
- посчитать продажи по дням и категориям;
- найти товары по названию и атрибутам;
- списать остаток и записать платеж одной транзакцией.
По этому списку видно модель доступа: чтение по ключу, обход связей, поиск по тексту или сканирование большого набора событий.
2. Определить основной тип нагрузки
- Заказы, платежи, остатки и другие операционные записи - OLTP, обычно PostgreSQL.
- Объекты с изменчивой структурой и чтением целиком - документная база.
- Быстрые временные данные по ключу - Redis рядом с основной базой.
- Поиск по тексту - поисковый индекс, не обязательно отдельная основная база.
- Агрегаты по большой истории - аналитическое хранилище.
- Обход связей на несколько шагов - графовая модель.
- Большие файлы - object storage.
Основной тип нагрузки один, даже если в системе есть задачи всех видов. Именно он определяет источник истины.
3. Записать обязательные гарантии
Ответьте на четыре вопроса:
- Какие операции обязаны быть атомарными?
- Можно ли читать данные с задержкой, и сколько она допустима?
- Что страшнее потерять: доступность системы или последнюю запись?
- Какая схема и какие ограничения должны проверяться самой базой?
Если списание денег и изменение остатка должны произойти вместе, это требование важнее моды на NoSQL. Если поисковый индекс можно перестроить из основной базы, его отставание в секунды обычно допустимо.
4. Подставить числа
Оцените объем данных, записей в секунду, чтений в секунду, срок хранения, допустимую задержку и рост за год. Слова «много» и «быстро» не помогают выбрать модель.
Например, сто заказов в секунду и отчеты за неделю - не повод сразу строить кластер Cassandra. Аналитика по десяти событиям на заказ за пять лет - уже причина отделить историю от операционной базы.
5. Сначала проверить существующую базу
PostgreSQL часто закрывает больше задач, чем кажется: jsonb для изменчивых атрибутов, полнотекстовый поиск и pg_trgm для каталога, рекурсивные запросы для иерархий, партиционирование для больших таблиц. Это не призыв натягивать одну базу на все, а способ не покупать распределенную сложность раньше времени.
Отдельное хранилище появляется после измеренного ограничения, а не после фразы «вдруг вырастем».
6. Посчитать цену второй базы
Вторая база - это еще и конвейер данных, отставание копии, сверка, резервное восстановление, мониторинг и новые навыки команды. Сравнивайте не стоимость лицензий, а полный вариант: железо, облачные услуги, часы эксплуатации и риск расхождения данных.
Если задачу можно решить индексом или настройкой существующей базы, второе хранилище обычно дороже.
Пример: маркетплейс
У магазина есть заказы, каталог, поиск, рекомендации, изображения и аналитика. Одна база на все необязательна, но источник истины должен быть понятен.
- Заказы, покупатели, остатки и платежи - PostgreSQL.
- Изменчивые атрибуты товаров - сначала
jsonb, отдельная MongoDB только при доказанной необходимости. - Кэш карточек и временные счетчики - Redis.
- Поиск по названию и описанию - сначала PostgreSQL FTS, затем Elasticsearch при нехватке релевантности или масштаба.
- Изображения и видео - S3, в PostgreSQL только метаданные и ссылки.
- История событий и тяжелые отчеты - ClickHouse с отдельной доставкой данных.
- Рекомендации через цепочки связей - Neo4j, если графовые обходы действительно нужны.
Cassandra появляется здесь только при очень большом и предсказуемом потоке событий, когда операционная база уже не справляется с записью.
Признаки ошибочного выбора
- Базу выбрали до списка запросов.
- Новую технологию взяли, потому что она популярна.
- Для обычного CRUD сразу завели несколько хранилищ.
- Основные деньги и заказы записывают только в кэш или поисковый индекс.
- Вторую базу добавили, но не решили, как синхронизировать и восстанавливать данные.
- Графовую или аналитическую базу используют как универсальную.
Что почитать дальше
- PostgreSQL или MongoDB - таблицы против документов.
- PostgreSQL или ClickHouse - когда выносить аналитику.
- Поиск: PostgreSQL FTS или Elasticsearch - когда отдельный поисковый движок оправдан.
- Cassandra, PostgreSQL или MongoDB - масштаб записи и его цена.
- Рекурсивный SQL или графовая СУБД - где проходит граница графовой задачи.
- Файлы: в базе данных или object storage - почему файл и его метаданные живут по-разному.
Коротко
- Выбор начинается с запросов, гарантий и чисел, а не с названия базы.
- PostgreSQL - разумная основа большинства приложений, остальные хранилища добавляют под специализированную нагрузку.
- Кэш, поисковый индекс и аналитическая копия не заменяют источник истины.
- Вторая база оправдана измеренным ограничением и готовностью поддерживать синхронизацию данных.