Совместное использование MongoDB и PostgreSQL


25

Мой текущий проект - это, по сути, запуск системы управления документооборотом.

Тем не менее, есть некоторые морщины (удивление, удивление). Хотя некоторые морщины довольно специфичны для проекта, я полагаю, что есть некоторые общие замечания и вопросы, которые не дают канонического ответа (который я мог бы найти в любом случае) и которые применимы к более широкой проблемной области. , Здесь много всего, и я не уверен, что он подходит для формата вопросов и ответов StackExchange, но я думаю, что это а) ответный вопрос и б) недостаточно конкретный, чтобы он мог принести пользу сообществу. Некоторые из моих соображений специфичны для меня, но я думаю, что этот вопрос может быть полезен любому, кто столкнулся с выбором SQL против NoSQL против обоих.

Фон:

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

TL; DR: я думаю, что № 5 ниже проходит тест на запах. Вы? У кого-нибудь есть опыт такой интеграции SQL и NOSQL в одном приложении? Я попытался перечислить все возможные подходы к этому классу проблем ниже. Я пропустил многообещающую альтернативу?

Сложности:

  • Есть много разных классов документов. Требования уже требуют десятки различных документов. Это число будет только расти. В лучшем случае можно использовать простой язык, специфичный для предметной области, генерацию кода и гибкую схему, чтобы эксперты в области могли обрабатывать добавление новых классов документов без вмешательства администраторов баз данных или программистов. (Примечание: уже известно, что мы доживаем до десятого правила Гринспуна )
  • Целостность предыдущих успешных записей является центральным требованием проекта. Данные будут важны для бизнеса. Полная семантика ACID при записи может быть принесена в жертву при условии, что вещи, которые действительно успешно написаны, остаются записанными.
  • Документы сами по себе сложные. Прототип документа в нашем конкретном случае потребует хранения 150+ отдельных частей данных на экземпляр документа. Патологический случай может быть на порядок хуже, но уж точно не два.
  • Единый класс документов - это движущаяся цель, подлежащая обновлению в более поздний момент времени.
  • Нам нравится бесплатный материал, который мы получаем от Django, когда подключаем его к реляционной базе данных. Мы хотели бы сохранить халяву без необходимости возвращаться к двум версиям Django, чтобы использовать форк django-nonrel. Выгрузка ORM полностью предпочтительнее, чем снижение до 1,3.

По сути, это путаница реляционных данных (типичные вещи вашего веб-приложения, такие как пользователи, группы и т. Д.), А также метаданные документа, которые нам понадобятся для нарезки и нарезки со сложными запросами в режиме реального времени) и данные документа (например, сотни полей, к которым у нас нет никакого интереса присоединяться или запрашивать - наш единственный вариант использования данных будет для показа одного документа, в который они были введены).

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

Предлагаемые решения:

1. Одна таблица на класс документа

Каждый класс документа получает свою собственную таблицу со столбцами для всех метаданных и данных.

Преимущества:

  • Стандартная модель данных SQL находится в игре.
  • Реляционные данные обрабатываются наилучшим образом. Мы денормализуем позже, если нам нужно.
  • Встроенный административный интерфейс Django удобен для анализа этих таблиц, и ORM может жить счастливо со 100% данными из коробки.

Недостатки:

  • Технический кошмар. Десятки (сотни?) Таблиц с (десятками?) Тысяч столбцов.
  • Логика уровня приложения, ответственная за решение, в какую именно таблицу писать. Делая имя таблицы параметром для запроса, воняет.
  • В основном все изменения бизнес-логики потребуют изменения схемы.
  • Патологические случаи могут потребовать чередования данных для отдельных форм в нескольких таблицах (см .: Каково максимальное количество столбцов в таблице PostgreSQL? ).
  • Вероятно, нам нужно было бы найти настоящего, честного и честного администратора баз данных, который, несомненно, в конечном итоге будет ненавидеть жизнь и нас.

2. EAV моделирование

Там есть просто таблица полей. Моделирование Entity-Attribute-Value уже хорошо понято. Я включил это для полноты. Я не думаю, что какой-либо новый проект, который будет запущен в 2013 году, намеренно использует подход EAV.

Преимущества:

  • Легко моделировать.

Недостатки:

  • Сложнее запросить.
  • Уровень БД больше не имеет прямого представления о том, что составляет один объект уровня приложения.
  • Мы бы потеряли проверку ограничений на уровне БД.
  • Количество строк в одной таблице будет расти в 100-1000 раз быстрее. Вероятно, в будущем болевая точка, в плане производительности.
  • Возможна ограниченная индексация.
  • Схема БД бессмысленна для ORM. Аккумуляторы в комплекте с веб-приложением сохраняются, но для пользовательских моделей данных требуются пользовательские запросы.

3. Используйте поля PostgreSQL hstore или json

Любой из этих типов полей поможет сохранить данные без схемы в контексте реляционной БД. Единственная причина , почему я не прыгаю к этому решению сразу это относительно новое (введено в версии 8.4 , так не что новая), у меня нулевой предыдущего воздействия на него , и я с подозрением. Это кажется мне неправильным по тем же причинам, по которым я чувствовал бы себя неловко, бросая все свои хорошие, легко нормализованные данные в Mongo - даже несмотря на то, что Mongo может обрабатывать ссылки между документами.

Преимущества:

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

Недостатки:

  • Нет опыта с этим, лично.
  • Это не похоже на очень часто используемую функцию. Похоже, что их рекомендуют людям, которые смотрят на решения NOSQL, но я не вижу много доказательств того, что их выбирают. Это заставляет меня думать, что я что-то упускаю.
  • Все сохраненные значения являются строками. Потерять проверку ограничений на уровне БД.
  • Данные в hstore никогда не будут отображаться пользователю, если они специально не просматривают документ, но метаданные, хранящиеся в более стандартных столбцах, будут. Мы будем использовать эти метаданные, и я опасаюсь, что довольно большие хранилища, которые мы будем создавать, могут иметь недостатки в производительности.

4. Полноценный документно-ориентированный

Сделайте все вещи документами (в смысле MongoDB). Создайте одну коллекцию типов Documentи назовите это день. Переведите все периферийные данные (включая данные об учетных записях пользователей, группах и т. Д.) В монго. Это решение, очевидно, лучше, чем моделирование EAV, но оно кажется мне неправильным по той же причине, по которой № 3 чувствовал себя неправильно - им обоим тоже нравится использовать молоток в качестве отвертки.

Преимущества:

  • Нет необходимости моделировать данные заранее. Имейте одну коллекцию с документами типа Documentи называйте это днем.
  • Известны хорошие характеристики масштабирования, если коллекция должна расти, чтобы охватить миллионы или даже миллиарды документов.
  • Формат JSON (BSON) интуитивно понятен для разработчиков.
  • Насколько я понимаю (что пока неопределенно), будучи параноиком по отношению к уровню записи, даже один экземпляр может обеспечить довольно надежную защиту данных в случае чего угодно и чего угодно, вплоть до сбоя жесткого диска.

Недостатки:

  • ORM - это окно для ствола Django. Халява, которая выходит из окна вместе с ней: фреймворк аутентификации, фреймворк сессий, интерфейс администратора, конечно же, многое другое.
  • Должны либо использовать возможности ссылок Монго (которые требуют многократных запросов), либо денормализовать данные. Мы не только теряем халяву, которую мы получили от Django, мы также теряем халяву, такую ​​как JOIN, которую мы считали само собой разумеющейся в PostgreSQL.
  • Безопасность данных. Когда кто-то читает о MongoDB, кажется, что всегда найдется хотя бы один человек, обращающийся к тому, как он потеряет ваши данные. Они никогда не ссылаются на конкретный случай, и все это может быть просто фигней или просто связано со старым пожаром по умолчанию и забыть о проблемах с записью, но это все еще беспокоит меня. Конечно, в любом случае мы будем использовать довольно параноидальную стратегию резервного копирования (если данные будут молча повреждены, это, конечно, может оказаться несущественным).

5. PostgreSQL и MongoDB

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

Преимущества:

  • Каждый бэкэнд делает только то, что у него хорошо получается.
  • Ссылки между моделями сохраняются без необходимости нескольких запросов.
  • Мы сохраняем батарейки, которые нам предоставил Django в отношении пользователей, сеансов и т. Д.
  • Нужна только одна documentsтаблица, независимо от того, сколько разных классов документов создано.
  • Реже запрашиваемые данные документа сильно отделены от гораздо более часто запрашиваемых метаданных.

Недостатки:

  • Для извлечения данных документа потребуется 2 последовательных запроса, сначала к базе данных SQL, а затем к MongoDB (хотя это не хуже, чем если бы те же данные были сохранены в Mongo и не денормализованы)
  • Письмо больше не будет атомарным. Запись против одного документа Mongo гарантированно является атомарной, и PG, очевидно, может гарантировать атомарность, но для обеспечения атомарности записи в обоих случаях потребуется логика приложения, без сомнения, с потерей производительности и сложности.
  • Два бэкэнда = два языка запросов = две разные программы с разными требованиями администратора = две базы данных, борющиеся за память.

Я бы пошел на столбец с JSONтипом данных. Не бойтесь использовать новые функции в Postgres - команда Postgres не выпускает нестабильные функции. И 9.2 на самом деле не так уж и ново). Кроме того, вы можете использовать новые функции JSON в 9.3, как только они появятся. Если вы всегда полностью обрабатываете документы в коде приложения (а не используете SQL), вы также можете хранить JSON в обычном textстолбце.
a_horse_with_no_name

Потенциальным ответчикам: пожалуйста, не стесняйтесь дать ответ! Однако, поскольку этот вопрос просуществовал довольно долго без «идеального» ответа, я намерен ответить на вопрос с полным посмертным опытом, как только мы внедрим его и перейдем к производству. Это может быть год в будущем, но не волнуйтесь - OP доставит. Я ожидаю, что это то, что те, кто поддержал / проголосовал за этот конкретный вопрос, сочли бы наиболее полезным: подтверждение того, что он работает, или объяснение того, какие контрольно-пропускные пункты убили параллельный вариант.
chucksmash

2
@chucksmash. В конце концов, вы пошли с # 5? Как вам удалось реализовать обе базы данных? Какие инструменты вы использовали? Если нет, почему?
xpanta

@chucksmash Все еще жду обещанной вами обратной связи.
Бхашит Парих

@chucksmash OP не доставил ... :(
Альберт Ротман,

Ответы:


13

Некоторые мысли ....

Как правило, не требуется хранить фрагменты тесно взаимосвязанной информации в разных системах. Шансы на несогласованность вещей значительны, и теперь вместо одной проблемы у вас две. Единственное, что вы можете сделать с Mongo, это использовать его для передачи или вывода данных. Я предпочитаю хранить все в PostgreSQL, насколько это возможно. Тем не менее, я хотел бы отметить, что это действительно требует экспертных знаний в программировании на PostgreSQL, и магазины не желают использовать расширенные функции. Я вижу несколько иной набор опций, чем вы. Поскольку мои предпочтения не указаны в списке, я отдам их вам.

Вероятно, вы можете разделить ваши метаданные на общие данные, данные, необходимые для классов, и данные документа. В связи с этим у вас будет общая таблица каталогов с базовой общей информацией плюс одна таблица на класс. В этой таблице у вас будет поле hstore, json или xml, в котором будут храниться остальные данные вместе со столбцами, в которых вы храните данные, которые должны быть существенно ограничены. Это уменьшит то, что вам нужно поместить в эти таблицы для каждого класса, но позволит вам использовать ограничения по своему усмотрению. Три варианта имеют разные проблемы и заслуживают отдельного рассмотрения:

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

JSON довольно новый и на самом деле мало что делает сейчас. Это не значит, что вы ничего не можете сделать с этим, но вы не собираетесь делать многое из коробки. Если вы это сделаете, вы можете рассчитывать на значительный объем программирования, вероятно, на plv8js или, если вы хотите придерживаться более старых сред, на plperlu или plpython. jsonлучше поддерживается в 9.3, хотя бы в текущих моментальных снимках разработки, поэтому, когда эта версия будет выпущена, все станет лучше.

xml - лучшая поддерживаемая из трех, с большинством функций и самой длинной историей поддержки. Опять же, это XML .....

Однако, если вы решили пойти вместе с Mongo и PostgreSQL, обратите внимание, что PostgreSQL поддерживает двухфазную фиксацию, что означает, что вы можете запускать операции записи, а затем выполнить команду, PREPARE TRANSACTIONи если это удастся, выполните атомарные записи в Mongo. Если это удастся, вы можете COMMITв PostgreSQL.


1
Это все отличные предложения. Я упоминал ранее об использовании hstore / json (и молча обесценивал xml, потому что, ну, xml), но я не думал об их использовании так, как вы рекомендуете. Помимо всего этого, предложение о фиксации фазы Postgres 2 - это золото. Я понятия не имел, что это существует. Спасибо за отличные предложения.
chucksmash

Двухэтапный коммит действительно является золотом. Это делает использование NoSQL в тандеме очень возможным. Особенно, если данные между двумя БД редко
связаны

0

Вы можете настроить механизм запросов, например Presto или Dremio, для объединения данных, находящихся в MongoDB и Postgres, с помощью одного запроса. Оба имеют коннекторы для каждой из этих баз данных (см. Документацию здесь и здесь ) и предлагают, соответственно, запустить «SQL на чем угодно» и «присоединиться к чему угодно».

Чтобы протестировать Presto, вы можете развернуть небольшой кластер в AWS EMR с Hadoop, Hive и Presto (добавьте оттенок, если вы не хотите использовать командную строку), он работает из коробки - обязательно следуйте этим инструкциям для настройки разъемы . Hive не является строго необходимым, но с его помощью вы можете создавать таблицы, используя результат объединений между Mongo и Postgres ( см. Примеры на этой странице ). На рынке также есть платная версия , которая (предположительно) сильно оптимизирована и имеет 30-дневную пробную версию.

Я не использовал Dremio, но есть несколько простых способов развернуть его в AWS, Azure или локально. На их веб-сайте есть несколько онлайн-курсов с доступом к «виртуальной лаборатории», которую вы можете использовать, чтобы бесплатно посещать занятия.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.