PostgreSQL или MongoDB: чтение и массовая запись дают разных победителей

|Автор: Редакция QUASA|5 мин чтения| 2
PostgreSQL или MongoDB: чтение и массовая запись дают разных победителей

Для проекта со множеством связанных сущностей и частыми изменениями нескольких записей разумной отправной точкой будет PostgreSQL. MongoDB имеет смысл рассматривать, когда приложение обычно читает и меняет самостоятельный документ целиком; большой поток таких записей усиливает этот аргумент. Выбор зависит от устройства данных и преобладающих операций.

В исследовании с приложением на Java Spring при чтении 100 тысяч записей медиана времени ответа составила 0,59 секунды для PostgreSQL и 1,97 секунды для MongoDB; при записи того же объёма — 50,49 и 29,00 секунды соответственно. Измерялось время ответа приложения на конкретные операции, поэтому результаты нельзя считать постоянной скоростью каждой базы.

Что измерялось в эксперименте

Для стенда создали данные интернет-магазина велосипедов: заказы, их состав, товары и пользователей. Запросы проходили через серверное приложение, а основная часть обращений к базам — через репозитории Java Spring. Кэширование было включено, первый результат каждой серии отбрасывали, затем операции повторяли. Приведённое время отражает работу связки приложения, модели данных и базы на данном стенде.

Кроме чтения и записи, проверяли удаление и поиск заказов по связанным данным. Удаление в показанном коде устроено как поиск записей с последующим удалением каждой в цикле; оно не показывает скорость единственной пакетной команды. Для поиска PostgreSQL использовал соединение таблиц, а MongoDB — конвейер агрегации с этапом $lookup. При таком устройстве запросов PostgreSQL быстрее собирал связанные записи, а MongoDB быстрее удаляла. Изменение схемы или последовательности команд способно изменить соотношение времени.

Связанные сущности: преимущество модели PostgreSQL

Если у заказа, товара, покупателя и остатков собственный жизненный цикл, таблицы с ключами позволяют хранить каждую сущность отдельно и собирать нужную комбинацию запросом. Это особенно полезно, когда один товар встречается во многих заказах, сведения о нём обновляются независимо, а приложение регулярно выбирает заказы по свойствам товара. Условия соединения и ограничения целостности тогда выражаются в схеме базы.

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

Документы: когда вложение оправданно

Рекомендации MongoDB по модели данных советуют вкладывать сведения, которые приложение обычно запрашивает или обновляет вместе. Отдельные ссылки уместнее, когда вложенный набор может расти без границ, дочерняя сущность существует сама по себе или дублирование трудно поддерживать. Документ заказа может быть удобной единицей чтения, если его состав и свойства действительно нужны одновременно; постоянно меняющийся общий каталог товаров разумнее оценивать отдельно.

Гибкость структуры не требует автоматически выбирать документную базу. Описание типов JSON в PostgreSQL показывает, что jsonb поддерживает запросы к содержимому и индексы. Если основные связи устойчивы, а меняется лишь набор дополнительных свойств товара, их можно хранить рядом с обычными столбцами. Однако обновление значения jsonb блокирует всю строку: очень крупный документ с частыми независимыми изменениями тоже требует осторожного проектирования.

Массовая запись и удаление

Результат записи делает MongoDB кандидатом для нагрузки, где приложение принимает много относительно автономных объектов. Но «массовая» в этом испытании означает объём обработанных записей, а не проверку всех вариантов пакетной вставки. В прикладном слое использовались методы сохранения объектов через репозитории; переносить полученное время на прямую команду базы, другую схему индексов или другой размер документа нельзя.

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

Транзакции и граница документа

Документация PostgreSQL о транзакциях описывает группу команд как действие по принципу «всё или ничего»: незавершённые изменения не видны другим транзакциям, а при откате отменяется вся группа. Это прямая модель для операции, в которой заказ, остаток и платёж должны измениться согласованно внутри одной базы. Транзакционная граница охватывает несколько таблиц без необходимости встраивать их в одну запись.

MongoDB поддерживает атомарное изменение одного документа, а документация о транзакциях нескольких документов описывает ACID-транзакции между коллекциями и сегментами распределённого кластера с гарантиями, зависящими от настроек чтения и записи. Там же указано, что распределённая транзакция обычно дороже записи одного документа. Если совместно изменяемые поля естественно помещаются в один документ, эта граница может упростить работу. Если обычная операция затрагивает разные самостоятельные документы, стоимость транзакций становится частью выбора; требование атомарности между сегментами следует рассматривать отдельно от транзакции внутри одной базы PostgreSQL.

Как выбрать под свою нагрузку

Решение удобно привязать к операции, без которой приложение не выполняет свою основную задачу:

  • Преобладают связи и совместные запросы: начать с PostgreSQL и таблиц, сохраняя общие сущности отдельно.
  • Преобладают цельные документы: рассмотреть MongoDB, если вложение соответствует чтению и обновлению, а размер вложенных данных остаётся управляемым.
  • Преобладает поток автономных записей: включить MongoDB в сравнение, сохранив в измерениях индексы и последующие запросы.
  • Нужны атомарные изменения раздельных записей: определить границу операции; для связей внутри одной базы удобен PostgreSQL, а для транзакций между сегментами оценить возможности и цену MongoDB.

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

Читайте также:

Поделиться:

Подпишитесь на рассылку

Получайте свежие новости Web3, AI и криптовалют прямо на вашу почту.

0