Антон Ларичев

Введение
Выбор базы данных — одно из самых дорогих архитектурных решений. Сменить ORM или фреймворк можно за неделю, а миграция между PostgreSQL и MongoDB растягивается на месяцы и часто требует переписывания бизнес-логики. В 2025 году граница между реляционными и документными СУБД размылась: PostgreSQL умеет работать с JSONB не хуже специализированных решений, а MongoDB добавила полноценные ACID-транзакции. Разберёмся, когда какой инструмент действительно уместен.
Модель данных
PostgreSQL — реляционная СУБД со строгой схемой. Вы заранее описываете таблицы, типы колонок, ограничения и внешние ключи. Это даёт предсказуемость и защищает от мусора в данных.
-- Создание таблицы пользователей с ограничениями
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
-- JSONB позволяет хранить произвольные настройки
settings JSONB DEFAULT '{}'
);
CREATE INDEX idx_users_settings ON users USING GIN (settings);
MongoDB хранит данные как BSON-документы в коллекциях. Схема гибкая: два документа в одной коллекции могут иметь разный набор полей.
// Вставка документа произвольной структуры
await db.collection('users').insertOne({
email: 'user@example.com',
createdAt: new Date(),
// Вложенные объекты без отдельных таблиц
profile: {
name: 'Анна',
interests: ['backend', 'devops']
}
});
Правило простое: если предметная область устоявшаяся и связи между сущностями важны — берите PostgreSQL. Если структура документа меняется часто, либо документы по своей природе иерархичны (товары маркетплейса, события аналитики) — MongoDB снимет головную боль с миграциями.
Транзакции и целостность
Исторически это был главный козырь PostgreSQL: полноценные ACID-транзакции с несколькими уровнями изоляции.
BEGIN;
-- Списываем деньги у отправителя
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
-- Зачисляем получателю
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
-- Если что-то пойдёт не так, изменения откатятся
COMMIT;
MongoDB с версии 4.0 поддерживает многодокументные транзакции, а с 5.0 они работают и в шардированных кластерах.
const session = client.startSession();
try {
await session.withTransaction(async () => {
// Обе операции либо выполнятся, либо откатятся вместе
await accounts.updateOne({ _id: 1 }, { $inc: { balance: -1000 } }, { session });
await accounts.updateOne({ _id: 2 }, { $inc: { balance: 1000 } }, { session });
});
} finally {
await session.endSession();
}
Но есть нюанс: транзакции в MongoDB обходятся дороже по латентности и не предназначены для высоконагруженных сценариев. Если у вас финтех, биллинг или склад — PostgreSQL по-прежнему безопаснее.
Запросы и индексы
SQL даёт мощный декларативный язык: JOIN, оконные функции, CTE, материализованные представления. Для аналитических отчётов это незаменимо.
-- Топ-5 авторов по числу публикаций за месяц
SELECT u.email, COUNT(p.id) AS posts_count
FROM users u
JOIN posts p ON p.author_id = u.id
WHERE p.created_at > NOW() - INTERVAL '30 days'
GROUP BY u.email
ORDER BY posts_count DESC
LIMIT 5;
MongoDB предлагает aggregation pipeline — последовательность стадий обработки документов.
const topAuthors = await db.collection('posts').aggregate([
// Фильтруем посты за последние 30 дней
{ $match: { createdAt: { $gte: new Date(Date.now() - 30 * 24 * 3600 * 1000) } } },
// Группируем по автору и считаем количество
{ $group: { _id: '$authorId', postsCount: { $sum: 1 } } },
{ $sort: { postsCount: -1 } },
{ $limit: 5 }
]).toArray();
Для простых выборок по ключу разница незаметна. Для сложной аналитики с пятью JOIN PostgreSQL выигрывает по выразительности и оптимизатору.
Масштабирование
MongoDB изначально проектировалась под горизонтальное масштабирование через шардирование. Достаточно выбрать shard key — и кластер сам распределит данные.
PostgreSQL традиционно масштабируется вертикально и через реплики на чтение. Шардирование возможно (Citus, partitioning), но требует ручной работы. Если вы заранее знаете, что данные не поместятся на один узел и нужны сотни терабайт — MongoDB снимет часть инженерных задач.
Частые ошибки
Выбор MongoDB ради «гибкости», когда данные строго реляционные. Через полгода вы вручную пишете JOIN на клиенте и теряете согласованность. Если сущности связаны внешними ключами — это сигнал в пользу PostgreSQL.
Хранение всего в JSONB в PostgreSQL. JSONB удобен для редко меняющихся атрибутов, но если 80% полей лежат внутри JSON, вы теряете типизацию и индексацию. Выносите горячие поля в колонки.
Игнорирование индексов в MongoDB. Без индекса коллекция в миллион документов превращает любой запрос в полное сканирование. Анализируйте план через explain('executionStats').
Многодокументные транзакции в MongoDB как замена реляционной модели. Они работают, но платой будет рост латентности и блокировок. Если транзакций много — берите PostgreSQL.
Отсутствие бэкапов и проверки восстановления. Любая СУБД бесполезна, если вы не умеете поднять её из бэкапа за разумное время.
Заключение
В 2025 году выбор сводится к простому принципу: PostgreSQL — дефолт для большинства бизнес-приложений, особенно где важны транзакции, отчётность и долгоживущая схема. MongoDB уместна, когда документная модель естественна для домена, нужна гибкая схема или планируется горизонтальное масштабирование с самого старта. Многие команды используют обе СУБД одновременно: PostgreSQL держит ядро данных, а MongoDB — события, логи или товарный каталог. Главное — принимать решение исходя из характера нагрузки и команды, а не из моды.






Комментарии
0