← назад к разделу

Когда начинаешь новый проект, рано или поздно встаёт вопрос: какую базу данных взять? Обычно выбирают либо по привычке («у нас всегда PG»), либо по моде («MongoDB — это NoSQL, а NoSQL современно»). Оба подхода приводят к проблемам.

Разберём, чем эти две базы отличаются по существу, и как понять, какая подходит для вашей задачи.

Разные базы — для разных задач

PostgreSQL — реляционная база данных. Данные хранятся в таблицах со строгой схемой: у каждой колонки есть тип, ограничения (NOT NULL, FOREIGN KEY), и строки из разных таблиц можно соединять через JOIN.

MongoDB — документная база. Данные хранятся в коллекциях документов, каждый документ — это JSON-объект. Схема гибкая: два документа в одной коллекции могут иметь разный набор полей.

Ни одна не лучше другой в целом. Они решают разные задачи.

Когда данные связаны между собой

Представьте интернет-магазин: заказ принадлежит покупателю, у покупателя есть адрес, заказ содержит товары, у товаров — категории и остатки на складе. Эти сущности постоянно ссылаются друг на друга.

Для таких данных лучше подходит PostgreSQL. JOIN-ы между таблицами — это его родная операция. Внешние ключи гарантируют, что не появится заказ с несуществующим покупателем. NOT NULL и CHECK ловят ошибки ещё до записи в базу.

-- Связи через внешние ключи — PG гарантирует целостность
CREATE TABLE orders (
    id          BIGSERIAL PRIMARY KEY,
    customer_id BIGINT REFERENCES customers(id),
    created_at  TIMESTAMP NOT NULL
);

MongoDB лучше подходит, когда данные читаются целиком, как один документ. Профиль пользователя со всеми настройками, заказ со всеми позициями, событие с произвольными атрибутами. Если типичный запрос — «дай мне этот объект целиком», документная модель выигрывает: всё хранится рядом и читается одним обращением.

Когда структура данных нестабильна

Раньше перед проектированием базы сначала проектировали схему — и это правило. Если поле появляется позже, пишется миграция, и все документы обновляются.

Иногда это неудобно. Каталог товаров — хороший пример: у куртки есть размер и материал, у телевизора — диагональ и разрешение, у книги — автор и ISBN. Если таблица одна, придётся либо делать десятки колонок (большинство будут пустыми), либо выносить атрибуты в отдельную таблицу «ключ–значение».

MongoDB справляется с этим проще: каждый документ хранит только свои поля.

// Куртка
{ "name": "Куртка зимняя", "size": "L", "material": "полиэстер" }

// Телевизор  
{ "name": "Телевизор 55", "diagonal": 55, "resolution": "4K" }

Но есть важная оговорка: если схема меняется хаотично — это не повод брать MongoDB. Это сигнал, что домен плохо спроектирован. Гибкость MongoDB не заменяет моделирование данных.

Транзакции: когда операция должна выполниться целиком или не выполниться вовсе

Перевод денег между счетами — классический пример: списать со одного счёта и зачислить на другой нужно как единое действие. Если что-то пошло не так посередине — откатить обе операции.

PostgreSQL поддерживает полноценные ACID-транзакции с самого начала. Транзакция на нескольких таблицах — обычная операция.

MongoDB добавил поддержку многодокументных транзакций в версии 4.0, но они дороже по накладным расходам, чем в PG. Если большая часть операций требует транзакций на нескольких документах — это сигнал, что схема изначально лучше легла бы в реляционную базу.

Объём данных и масштабирование

Пока данных немного (до нескольких сотен гигабайт на одном сервере), обе базы работают одинаково хорошо. Разница появляется при росте.

PostgreSQL отлично справляется на одном мощном сервере. Партиционирование таблиц (разбивка по дате или диапазону ключей) решает большинство проблем с производительностью. Горизонтальное масштабирование на несколько серверов возможно, но требует отдельного инструмента (Citus).

MongoDB изначально проектировался под горизонтальное масштабирование. Sharded cluster — стандартный режим работы больших кластеров. Если заранее ясно, что данных будет десятки терабайт и более одного сервера — MongoDB упрощает инфраструктуру.

PostgreSQL + jsonb: третий вариант, о котором часто забывают

Между «чистым реляционным» и «чистым документным» есть промежуточный вариант: в PostgreSQL есть тип jsonb, который позволяет хранить произвольный JSON прямо в колонке, строить по нему индексы и делать поиск внутри JSON.

CREATE TABLE product (
    id          BIGSERIAL PRIMARY KEY,
    category_id BIGINT REFERENCES category(id),
    name        TEXT NOT NULL,
    price       NUMERIC(10,2) NOT NULL,
    attributes  JSONB NOT NULL DEFAULT '{}'::jsonb
);

-- GIN-индекс для быстрого поиска по содержимому JSON
CREATE INDEX product_attributes_gin ON product USING GIN (attributes);

-- Найти товары красного цвета
SELECT * FROM product WHERE attributes @> '{"color": "red"}';

Это даёт гибкость атрибутов (как в MongoDB) при сохранении реляционных связей, внешних ключей и транзакций. Если задача звучит как «нам нужна гибкость атрибутов, но данные связаны» — попробуйте jsonb прежде чем переходить на MongoDB.

Что умеет каждая база

ЗадачаЧто лучше
CRUD-сервис с понятной схемой и связямиPostgreSQL
Биллинг, бухгалтерия, финансыPostgreSQL
Каталог товаров с разными атрибутамиMongoDB или PG + jsonb
Профиль пользователя с вложенными даннымиMongoDB или PG + jsonb
Лента событий / логиMongoDB, ClickHouse
Гео-данныеPostgreSQL + PostGIS
Полнотекстовый поиск с фильтрамиOpenSearch / Elasticsearch
Кэш, сессииRedis
Аналитика и агрегатыClickHouse / DuckDB

Операционная сторона

PostgreSQL — зрелый инструмент с десятилетиями практики. Миграции через Flyway или Liquibase, мониторинг через pg_stat_* и pgAdmin, резервное копирование и репликация — всё это хорошо изучено и отработано.

MongoDB требует другого набора знаний: индексы строятся по другим правилам, шардинг — отдельная инженерная дисциплина, бэкап sharded cluster нетривиален. Если в команде нет человека с реальным опытом MongoDB на продуктиве — это риск при первой серьёзной проблеме.

Типичные ошибки при выборе

«MongoDB — потому что схема может меняться». Гибкость схемы не отменяет необходимость проектировать данные. Через год, если никто не писал миграции, никто не знает, какие документы в коллекции валидны.

«Возьмём обе для гибкости». Два набора миграций, два мониторинга, два бэкапа, риск рассинхрона данных. Две базы берут тогда, когда природа задач реально разная: например, транзакционные данные в PG и растущий лог событий в MongoDB.

«PG + jsonb всегда заменит MongoDB». При глубокой вложенности (несколько уровней массивов внутри JSON) запросы на jsonb становятся менее читаемыми и медленнее, чем эквивалент в MongoDB. Для истинно документной модели MongoDB удобнее как основной инструмент.

«MongoDB не нужны миграции». Нужны. Новое обязательное поле, переименование, изменение типа — это те же миграции, просто в MongoDB их никто не пишет по соглашению, и это создаёт проблемы позже.

Коротко

  • PostgreSQL лучше, когда данные связаны между собой и нужны JOIN-ы, транзакции, внешние ключи.
  • MongoDB лучше, когда данные читаются целиком как документы, схема разнородная, а масштаб предполагает несколько серверов.
  • PostgreSQL + jsonb — промежуточный вариант: гибкость JSON при сохранении реляционных гарантий.
  • Выбор по моде («NoSQL модно») или по привычке («у нас всегда PG») ведёт к проблемам.
  • MongoDB поддерживает транзакции, но они дороже — если транзакции нужны постоянно, скорее всего нужен PG.
  • Операционная зрелость команды имеет значение: MongoDB требует специфических знаний.
  • Две базы в одном сервисе оправданы только когда природа задач реально разная.

Что почитать дальше

  • Раздел про PostgreSQL — ACID, репликация, партиционирование.
  • Раздел про MongoDB — replica set, sharded cluster, моделирование документов.
  • Монолит, модульный монолит или микросервисы — другой архитектурный выбор.