Где схема — в базе или в коде
Вопрос “Postgres или MongoDB” на самом деле спрашивает не про базы данных, а про то, кто отвечает за структуру данных. В реляционных системах схема жёстко задана таблицами, и любое её изменение требует миграции. В документных базах схема живёт в коде приложения, а база хранит произвольные JSON-объекты без ограничений на структуру.
Когда разработчики выбирают документную базу, они получают возможность менять форму записи без миграций. Если нужно добавить новое поле, достаточно просто начать его писать — база примет новый формат без изменений в схеме. Вложенные структуры тоже становятся проще: вместо соединений таблиц можно хранить все связанные данные в одном документе. Но за эту гибкость приходится платить: согласованность между документами, транзакции и сложные запросы становятся задачей приложения.
Современный Postgres закрывает значительную часть документных сценариев с помощью полей JSON и JSONB. Можно хранить произвольные структуры, индексировать их и строить запросы с условиями на вложенные поля. Однако у этого подхода есть фундаментальные ограничения, которые проявляются не сразу, а по мере роста объёмов данных и сложности запросов.
Что на самом деле даёт документная модель
Документные базы предлагают три ключевых преимущества, которые особенно ценны в определённых сценариях:
-
Эволюция схемы без миграций Когда структура данных часто меняется, документная модель позволяет добавлять новые поля без остановки системы. В реляционной базе каждое изменение схемы требует миграции, которая может занять значительное время на больших объёмах данных. В документной базе новые поля просто появляются в новых записях, а старые остаются в прежнем формате.
-
Вложенность без соединений Связанные данные можно хранить в одном документе вместо нескольких таблиц. Это устраняет необходимость в соединениях (JOIN), которые часто становятся узким местом производительности. Например, заказ с товарами и информацией о клиенте можно хранить как один JSON-объект вместо трёх связанных таблиц.
-
Гибкость структуры Разные документы в одной коллекции могут иметь разную структуру. Это полезно, когда данные по своей природе неоднородны — например, события с разными наборами полей или продукты с различными характеристиками.
Однако эти преимущества не бесплатны. За гибкость приходится платить согласованностью, транзакциями и аналитическими возможностями.
Цена гибкости: что переходит в код приложения
Когда разработчики выбирают документную базу, они неявно соглашаются взять на себя часть работы, которую обычно выполняет СУБД:
-
Согласованность между документами В реляционных базах транзакции обеспечивают атомарность операций над несколькими таблицами. В документных базах транзакции либо ограничены одним документом, либо требуют реализации на уровне приложения. Если два документа должны обновляться согласованно, разработчикам придётся писать код, который это обеспечит.
-
Сложные запросы Аналитические запросы, которые в реляционных базах пишутся на SQL, в документных базах часто приходится реализовывать в коде приложения. Например, агрегацию данных по нескольким коллекциям или сложные условия фильтрации.
-
Отчётность Построение отчётов с группировкой, агрегацией и соединением данных становится задачей приложения. В реляционных базах такие отчёты можно написать одним SQL-запросом, в документных — приходится собирать данные по частям и обрабатывать их в коде.
-
Ограничения целостности Внешние ключи, уникальные ограничения и проверки данных на уровне базы в документных системах либо отсутствуют, либо реализованы ограниченно. Разработчикам приходится обеспечивать целостность данных на уровне приложения.
Эти ограничения особенно заметны в системах, где данные должны быть согласованы между разными частями приложения или где требуется сложная аналитика.
Как Postgres закрывает документные сценарии
Современный Postgres предлагает мощную поддержку JSON через типы данных JSON и JSONB. Это позволяет:
- Хранить произвольные структуры данных в одном поле
- Индексировать вложенные поля для быстрого поиска
- Строить запросы с условиями на вложенные структуры
- Обновлять отдельные части JSON-документов
Например, можно хранить заказ как JSON-объект с вложенными товарами и информацией о клиенте, а затем искать заказы по определённым товарам или фильтровать по дате заказа.
Однако у этого подхода есть фундаментальные ограничения:
-
Производительность обновлений Когда JSON-документ часто обновляется, особенно если изменения затрагивают вложенные структуры, Postgres приходится перезаписывать весь документ. В специализированных документных базах такие операции оптимизированы лучше.
-
Глубина вложенности Чем глубже вложенность структуры, тем сложнее становится писать эффективные запросы. В документных базах оптимизатор запросов лучше приспособлен для работы с глубокими структурами.
-
Аналитические запросы Хотя Postgres поддерживает JSON-функции, сложные аналитические запросы на больших объёмах данных могут работать медленнее, чем в специализированных системах.
-
Объём данных Когда объём JSON-данных становится значительным, производительность начинает зависеть от того, насколько эффективно используются индексы и как часто происходят обновления.
Когда Postgres перестаёт справляться
Есть несколько признаков, по которым видно, что JSON в Postgres перестаёт быть эффективным решением:
-
Частые обновления вложенных структур Если приложение часто обновляет массивы или объекты внутри JSON-документов, производительность может значительно упасть. Postgres приходится перезаписывать весь документ при каждом изменении.
-
Глубокие запросы по вложенным полям Когда запросы требуют доступа к глубоко вложенным полям или сложных операций с массивами, производительность может стать проблемой. В документных базах такие операции оптимизированы лучше.
-
Большие объёмы данных Когда объём JSON-данных превышает определённый порог (который зависит от конкретной нагрузки), производительность запросов начинает деградировать. Это связано с тем, что Postgres не оптимизирован для работы с большими объёмами слабоструктурированных данных.
-
Сложные аналитические запросы Если приложение требует сложной аналитики с группировкой, агрегацией и соединением данных из разных JSON-документов, Postgres может оказаться менее эффективным, чем специализированные системы.
-
Необходимость в распределённых транзакциях Когда данные должны быть согласованы между несколькими узлами, документные базы часто предлагают более гибкие решения, чем реляционные системы.
Как понять, что выбор сделан правильно
Есть несколько признаков, по которым можно судить о правильности выбора базы данных:
-
Структура данных стабильна Если схема данных меняется редко, а запросы стандартные, реляционная база будет хорошим выбором. Postgres с его поддержкой JSON может закрыть многие сценарии, где нужна гибкость.
-
Данные вложенные, но не слишком глубокие Если данные естественным образом представляются в виде вложенных структур, но глубина вложенности не превышает двух-трёх уровней, JSON в Postgres может быть хорошим решением.
-
Запросы простые и предсказуемые Если большинство запросов сводится к простой фильтрации или выборке по индексам, реляционная база справится лучше.
-
Нужна аналитика и отчётность Если приложение требует сложных аналитических запросов, реляционная база будет более подходящим выбором.
-
Транзакции важны Если данные должны обновляться атомарно в нескольких местах, реляционная база обеспечит лучшую поддержку транзакций.
Признаки того, что переезжают зря
Есть и обратные признаки, которые говорят о том, что выбор базы данных может быть неверным:
-
Приложение эмулирует транзакции Если разработчики пишут код для обеспечения согласованности между документами, возможно, стоит рассмотреть реляционную базу.
-
Запросы становятся слишком сложными Если запросы к JSON-данным становятся слишком сложными и медленными, возможно, стоит перейти на специализированную документную базу.
-
Частые обновления вложенных структур Если приложение часто обновляет массивы или объекты внутри JSON-документов, документная база может оказаться более эффективной.
-
Данные слишком неоднородны Если документы в одной коллекции имеют сильно различающуюся структуру, документная база может быть более подходящим выбором.
-
Нужна распределённая обработка Если данные должны обрабатываться на нескольких узлах с высокой доступностью, документные базы часто предлагают более гибкие решения.
Тупик: выбор по производительности на синтетическом тесте
Самая распространённая ошибка при выборе базы данных — ориентация на результаты синтетических тестов. Производительность базы данных зависит от множества факторов, и универсального лидера не существует.
Например, тест может показать, что MongoDB быстрее на запись, чем Postgres. Но это не значит, что MongoDB подойдёт для всех задач с частыми записями. Производительность зависит от:
-
Характера операций Одни базы лучше справляются с простыми записями, другие — со сложными запросами. Одни оптимизированы для чтения, другие — для записи.
-
Структуры данных Производительность зависит от того, как данные организованы. Вложенные структуры могут быть быстрее в документных базах, но медленнее в реляционных.
-
Объёма данных На малых объёмах разница может быть незаметна, но на больших объёмах она становится критической.
-
Характера запросов Одни базы лучше справляются с простыми запросами, другие — со сложными аналитическими.
-
Конфигурации системы Производительность зависит от аппаратных ресурсов, конфигурации базы и сетевых условий.
Поэтому выбор базы данных должен основываться не на синтетических тестах, а на реальных требованиях приложения и характере данных.
Позиция редакции
Выбор между Postgres и документной базой зависит от того, где удобнее хранить схему данных: в базе или в коде приложения. Если структура данных стабильна, а запросы стандартные, реляционная база будет хорошим выбором. Postgres с его поддержкой JSON закрывает значительную часть документных сценариев, но не все.
Если же данные часто меняют структуру, а запросы простые, документная база может оказаться более подходящим выбором. Однако если приложение начинает эмулировать транзакции или соединения, возможно, выбор был неверным.
Эта позиция неверна в следующих случаях:
-
Данные слишком неоднородны Если документы в одной коллекции имеют сильно различающуюся структуру, документная база может быть более эффективной.
-
Нужны частые обновления вложенных структур Если приложение часто обновляет массивы или объекты внутри JSON-документов, специализированная документная база справится лучше.
-
Требуется распределённая обработка Если данные должны обрабатываться на нескольких узлах с высокой доступностью, документные базы часто предлагают более гибкие решения.
-
Запросы слишком сложные Если приложение требует сложных аналитических запросов на больших объёмах данных, специализированная документная база может оказаться более эффективной.
В современном Postgres есть мощная поддержка JSON, которая закрывает многие документные сценарии, но не все. Выбор базы данных должен основываться на реальных требованиях приложения, а не на синтетических тестах.