Статьи

MongoDB против SQL: день 14

Первоначально Написано Базз Москетти

Добро пожаловать в нашу серию блогов, в которых освещаются различия между разработкой приложения с MongoDB и RDBMS / SQL. На прошлой неделе мы добавили номера телефонов в наше приложение. На этой неделе все станет немного сложнее.

Еще раз, давайте рассмотрим структуру, которую мы использовали, чтобы организовать наше обсуждение:

  • Мы используем Java
  • Предположим, у нас есть слой доступа к данным между нашим приложением и MongoDB
  • Что касается даты, которая учитывается при рассмотрении примеров, рассматривайте их как индикаторы относительного прогресса, а не фактическое время, необходимое для выполнения задачи.
  • Мы не будем вдаваться в исключения или обработку ошибок. Мы не будем путать код с шаблонной или персисторной логикой, которая не меняется со дня на день. Мы не будем входить в соединение с базой данных или другие ресурсы установки. Основное внимание будет уделено основному коду обработки данных.

SQL против MongoDB: день 14

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

n4.put(“geo”, “US-EAST”);
n4.put(“startupApps”, new String[] {“app1”, “app2”, “app3”});
list2.add(n4);
n5.put(“geo”, “EMEA”);
n5.put(“startupApps”, new String[] {“app6”});
n5.put(“useLocalNumberFormats”, false):
list2.add(n5);
m.put(“preferences”, list2)

n6.put(“optOut”, true);
n6.put(“assertDate”, someDate);
seclist.add(n6);
m.put(“attestations”, seclist)
m.put(“security”, mapOfDataCreatedByExternalSource);

Все еще довольно легко добавить эти данные в структуру, но есть несколько вещей, на которые следует обратить внимание:

  1. Обратите внимание, что мы пытаемся учесть две разные географии. В зависимости от того, где вы находитесь, у вас могут быть разные приложения при запуске в вашем решении. Поэтому мы легко смоделируем это как список структур, в которых поле «гео» может быть использовано в качестве ключа.
  2. Иногда вам будут представлены данные, которые вы абсолютно не можете контролировать. Вы не обязательно хотите манипулировать данными; Вы просто хотите сохранить его в той форме, в которой он представлен. Когда вам нужно извлечь данные обратно, вам нужно извлечь ту же самую фигуру, которую вы получили, и передать ее другому коду для обработки, не беспокоясь (или не обрабатывая) содержимое фигуры.

Теперь давайте посмотрим на постоянный код, который нам нужно написать, чтобы получить все это.

SQL Day 14

На данный момент объем кода для обработки существующей работы в течение дня 1-5, а также наш новый список приложений для запуска и новые таблицы, которые необходимы для его сохранения, будет занимать страницу или более. Просто вернитесь к Дню 3 и утроите его. Поэтому мы не будем останавливаться на этих вопросах.

Но теперь, когда мы в процессе разработки, у нас могут возникнуть две неприятные уступки в дизайне из-за усталости или проблем с выходом на рынок:

  1. Команда разработчиков решает неправильно моделировать новую таблицу, называемую приложениями для запуска, с необходимыми внешними ключами, управлением ключами и дополнительными объединениями. Вместо этого, признавая, что регионы представляют собой небольшой набор и не меняются часто, были созданы два новых столбца «APPS-US-EAST» и «APPS-EMEA». Каждый столбец содержит список имен приложений, разделенных точкой с запятой, например. «App1; app2; app3». Это часто повторяемая практика «перегрузки столбцов», когда сложная структура форматируется / кодируется в другие простые текстовые столбцы, чтобы избежать утомительной настройки большего количества таблиц и потенциального изменения многих объединений. Эта практика лишает возможности осуществлять надлежащее управление данными и налагает дополнительную логику декодирования данных на всех потребителей во всех приложениях на всех языках.
  2. Представленная карта данных безопасности произвольной и потенциально изменяющейся формы, команда разработчиков выбирает одно из следующих действий:

    1. Выберите подмножество известных полей и установите их в новые столбцы. Полученная верность и прозрачность полностью компенсируются потерей общей способности к постоянству.
    2. Преобразование карты в CLOB данных в некоторой форме ASCII. Это сохраняет постоянство общего, но данные не могут быть хорошо запрошены в базе данных и заставляет всех читателей и писателей на всех языках придерживаться одной и той же логики кодирования / декодирования.
    3. Преобразование карты в BLOB сериализованной Java. Это хуже всего: данные не могут быть запрошены, они доступны ТОЛЬКО для Java, и существует связь во время компиляции между сериализованной формой в базе данных и представлением, требуемым при десериализации.

MongoDB День 14

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

XXXXXПерейдем к чему-то, что, я уверен, многие из вас спрашивают: а что если нам действительно нужно объединиться?

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

Давайте теперь предположим, что мы хотим добавить транзакции телефонных звонков в нашу базу данных. Понятно, что транзакции — это отношения «ноль или больше», где «больше» может означать гораздо больше. И это имеет тенденцию расти со временем без ограничений. В этом случае использования дизайна данных в MongoDB, как и в RDBMS, целесообразно моделировать транзакции в новой отдельной коллекции.

Мы будем использовать вызывающий номер в качестве неуникального ключа в коллекции транзакций, и каждый документ будет содержать целевой номер (вызываемый номер) и продолжительность вызова в секундах:

Ранее мы исследовали и подробно рассмотрели некоторые проблемы, создаваемые зомби и внешними объединениями, а также разворачивание набора результатов в пространстве СУБД (день 5), поэтому в целях упрощения логики объединения в MongoDB давайте намеренно упростим SQL:

В дополнение к тому, что очень четко прослеживается взаимосвязь 1: N между контактами и телефонами, теперь мы также рассмотрим взаимосвязи от 1 до N, которые включают цели вызовов. Затем возникает задача: «Как превратить прямоугольник, возвращающийся в моем результате, в пригодный для использования список?»

И ответ заключается в том, что этот SQL будет работать только в том случае, если мы запросим один или все идентификаторы:

  • Если мы запрашиваем один идентификатор, например, добавляя «и A.id = ‘G9’» в SQL, то мы можем накапливать вызывающий номер и номера назначения на уровне доступа к данным и сортировать / назначать их.
  • Если мы запрашиваем все идентификаторы, мы можем проследить весь набор результатов и построить карту на основе идентификатора и использовать ту же логику в пуле выше.

Это способ, которым мы можем отменить этот набор результатов, когда мы хотим получить все идентификаторы и их телефонные транзакции:

В итоге мы получаем карту данных, которая передается обратно на наш уровень доступа к данным, в котором сначала указывается идентификатор, затем номер и, наконец, список целей вызова.

Проблема, конечно, заключается в том, что очень часто проект требует либо возможности вернуть частичный результат на уровень доступа к данным, либо разработчик не хочет иметь дело со сложностью кода раскрутки. Традиционное решение? Надежный ЗАКАЗАТЬ ПО:

Использование ORDER BY здесь не в первую очередь для управления окончательным упорядочением данных для представления; это настроить набор результатов для более удобного раскручивания. Когда мы повторяем набор результатов, когда мы обнаруживаем, что идентификатор изменяется с G10 на G9, мы знаем, что мы закончили со всеми элементами G10, и мы можем вернуть управление нашему вызывающему. Однако логика, которую мы делаем для построения карты списков, в значительной степени совпадает с тем, что мы видели в предыдущем примере.

И если индексы не настроены должным образом и / или объединенные наборы не являются относительно небольшими, либеральное использование ORDER BY может оказать значительное влияние на производительность системы.

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

Затем мы бросаем его в движок базы данных, скрещиваем пальцы, и позже наш набор результатов возвращается, а затем мы должны его разобрать. Чем больше соединений у нас в запросе, тем больше разборки. В реальном мире мы обычно говорим о трех, иногда четырех или более N-way соединениях, чтобы собрать всю информацию, которую мы хотим. И для каждой дополнительной таблицы, к которой вы присоединяетесь, вы несете больше логики разборки. И возможное дополнительное влияние на производительность, если для содействия процессу используется ORDER BY.

В MongoDB философия другая. MongoDB — это сборка вещей. В этом первом примере мы будем использовать подход «N + 1 выбор», чтобы на данный момент все было просто:

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

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

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

Вот как будет выглядеть соединение в MongoDB:

Здесь есть несколько вещей, на которые стоит обратить внимание. Во-первых, это не намного больше кода, чем мы видели в нашем примере SQL. Это, конечно, выигрывает от того, что вообще нет оператора SQL. То, что мы видим, является единственным кусочком логики, который необходим.

Кроме того, для любого, кто придет позже для отладки или изменения этого, способ построения кода теперь очень логичен и последовательн — и дружественен Java. Имеет смысл, как мы можем перебрать список карт и извлечь из них номер телефона. Особенно удобно и гибко то, что нам не нужно явно указывать цель и продолжительность; вместо этого мы можем просто взять всю подструктуру, вставить ее в список и вернуть обратно на родительскую карту. В конце концов, мы по-прежнему располагаем той же картой идентификаторов внизу, но мы получаем гораздо большую гибкость и ясность.

Мы упомянули выше, что мы использовали подход «N + 1 выбор» для простоты. Во многих случаях производительность может быть вполне приемлемой, особенно если относительные размеры каждого уровня в каскаде поиска составляют от 1 до многих (например, 10 или более), а не 1: 1. Но, как мы узнали в первый день, MongoDB — это выбор. Приложив немного больше работы, мы можем изменить логику, чтобы получать данные целого уровня, извлекая весь набор ключей для передачи на поиск следующего уровня. Легко программно создать и передать в MongoDB тысячи элементов в так называемом «списке» для поиска. Мы можем даже смешивать и сочетать эти два подхода в соответствии с нашими потребностями. В конце концов, логика полной выборки остается ясной, гибкой и масштабируемой, поскольку сложность запроса со временем увеличивается.

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