Використання MongoDB та PostgreSQL разом


25

Мій поточний проект, по суті, є запуском системи управління документами.

Сказане, є деякі зморшки (здивування, здивування). Хоча деякі зморшки досить специфічні для проекту, я вважаю, що виникають деякі загальні спостереження та питання, які не мають канонічної відповіді (що я міг би знайти в будь-якому випадку) і які застосовні до ширшої проблемної області . Тут багато чого, і я не впевнений, що це добре підходить для формату питань StackExchange Q&A, але я вважаю, що це: a) відповідне питання і b) недостатньо специфічне, що може принести користь громаді. Деякі мої міркування специфічні для мене, але я думаю, що питання може бути корисним для всіх, хто стикається з рішенням щодо SQL проти NoSQL проти обох.

Фон:

Веб-додаток, який ми будуємо, містить дані, що мають явний реляційний характер, а також дані, орієнтовані на документи. Ми хотіли б мати наш торт і теж його з'їсти.

TL; DR: Я думаю, що №5 нижче проходить тест на запах. Чи ти? Хтось має досвід такої інтеграції SQL та NOSQL в одному додатку? Я намагався перерахувати всі можливі підходи до цього класу проблем нижче. Я пропустив багатообіцяючу альтернативу?

Складності:

  • Існує багато різних класів документів. Вимоги вже вимагають десятки різних документів. Це число завжди зросте. Найкращим можливим випадком може бути той варіант, у якому ми могли б використовувати просту мову, специфічну для домену, генерацію коду та гнучку схему, щоб доменні експерти могли впоратися з додаванням нових класів документів без втручання DBA або програмістів. (Зауважте: вже відомо, що ми живемо десятим правилом Грінспуна )
  • Цілісність попередніх успішних записів є центральною вимогою проекту. Дані будуть критично важливими для бізнесу. Повна семантика ACID на записі може бути принесена в жертву за умови, що речі, які є успішно написаними, залишаються записаними.
  • Документи самі по собі є складними. Документ-прототип у нашому конкретному випадку вимагатиме зберігання 150+ різних фрагментів даних на примірник документа. Патологічний випадок міг бути на порядок гіршим, але точно не на два.
  • Один клас документів - це рухома ціль, що підлягає оновленню в подальшому періоді часу.
  • Нам подобаються безкоштовні речі, які ми отримуємо від Django, коли ми підключаємо їх до реляційної бази даних. Ми хотіли б зберегти халяви без необхідності відскакувати дві версії Django, щоб використовувати вилку django-nonrel. Демпінгом ОРМ цілком є ​​кращим, ніж пониження до 1,3.

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

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

Запропоновані рішення:

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

Кожен клас документа отримує власну таблицю зі стовпцями для всіх метаданих та даних.

Переваги:

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

Недоліки:

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

2. Моделювання EAV

Є просто таблиця полів. Моделювання сутність-атрибут-значення вже добре зрозуміло. Я включив його для повноти. Я не думаю, що будь-який новий проект, розпочатий у 2013 році, не міг би спеціально застосовувати підхід EAV.

Переваги:

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

Недоліки:

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

3. Використовуйте PostgreSQL hstore або json поля

Будь-який із цих типів полів зробив би трюк для зберігання безхемних даних у контексті реляційної БД. Єдина причина, що я не переходжу до цього рішення одразу - це відносно нове (представлене у версії 8.4, не таке вже й нове), у мене до нуля попереднє опромінення його, і я підозріло. Мені здається, що я помиляюсь з тих самих причин, що мені було б неприємно перекидати всі мої приємні, легко нормалізовані дані в Монго - навіть якщо Монго може обробляти посилання між документами.

Переваги:

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

Недоліки:

  • Немає досвіду з цим особисто.
  • Це не схоже на дуже високо використовувану функцію. Схоже, їх досить рекомендують людям, які дивляться на рішення NOSQL, але я не бачу багато доказів того, що їх обирають. Це змушує мене думати, що я повинен щось бракувати.
  • Усі збережені значення - це рядки. Пройдіть перевірку обмежень на рівні DB.
  • Дані в hstore ніколи не будуть відображатися користувачеві, якщо вони спеціально не переглянуть документ, але метадані, збережені в більш стандартних стовпцях, будуть. Ми обіграємо ці метадані, і я переживаю, що досить великі місця, які ми будемо створювати, можуть мати недоліки в продуктивності.

4. Перейдіть на документ повністю

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

Переваги:

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

Недоліки:

  • ORM знаходиться у вікні для магістралі Django. Халяви, які виходять у вікно з нею: автентична рамка, рамки сеансів, адміністраторський інтерфейс, безумовно, багато іншого.
  • Потрібно або використовувати можливості посилання на монго (які потребують декількох запитів), або денормалізувати дані. Ми не тільки втрачаємо халяви, які отримали від Django, ми також втрачаємо халяви, як ПРИЄДНАЙТЕСЬ, які ми сприйняли як належне в PostgreSQL.
  • Безпека даних. Коли хтось читає про MongoDB, то, здається, завжди знайдеться принаймні одна людина, яка посилається на те, як вона зробить і втратить ваші дані. Вони ніколи не цитують особливого явища, і все це може бути просто виїмкою або просто пов'язаним зі старим вогнем за замовчуванням і забути про занепокоєння, але це все одно мене хвилює. Ми, звичайно, будемо використовувати досить параноїдальну стратегію резервного копіювання в будь-якому випадку (якщо дані мовчки пошкоджені, це, звичайно, може бути несуттєвим.).

5. PostgreSQL і MongoDB

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

Переваги:

  • Кожен бекенд робить лише те, у чому добре.
  • Посилання між моделями зберігаються, не вимагаючи декількох запитів.
  • Ми намагаємось зберегти акумулятори, які нам подарував Джанго, що стосується користувачів, сеансів тощо.
  • Потрібна лише одна documentsтаблиця незалежно від кількості різних класів документів.
  • Рідко запитувані дані документа сильно відокремлюються від набагато частіше запитуваних метаданих.

Недоліки:

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

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

Потенційним відповідачам: будь ласка, не соромтесь надати відповідь! Оскільки це питання збереглося досить довго, не маючи «ідеальної» відповіді, я маю намір відповісти на це питання з повним посмертним досвідом після того, як ми реалізували та перейшли до виробництва. Можливо, це буде рік у майбутньому, але не хвилюйтесь - ОП виконає. Я думаю, що саме те, хто віддав перевагу / підтримав саме це питання, виявиться найбільш корисним: перевірка того, чи він працює, або пояснення того, які дорожні блокади вбили паралельний варіант.
Чакмаш

2
@chucksmash. Зрештою, ти пішов з №5? Як вам вдалося реалізувати обидва dbs? Якими інструментами ви користувалися? Якщо ні, то чому?
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і якщо це вдасться зробити атомний запис у Монго. Якщо це вдасться, ви можете COMMITв PostgreSQL.


1
Це все чудові пропозиції. Я вже згадував про використання hstore / json (і мовчки скидав xml, тому що, ну, xml), але не думав використовувати їх так, як ви рекомендуєте. На додаток до всього, пропозиція по фазі Postgres 2 - це золото. Я б не знав, що це існує. Дякуємо за чудові пропозиції.
chucksmash

Двофазова комісія дійсно є золотом. Це робить використання NoSQL в тандемі дуже здійсненним. Особливо, якщо дані між двома БД взаємозв'язуються рідко, і вони здебільшого вирішують різні проблеми
haknick

0

Ви можете налаштувати механізм запитів, наприклад Presto або Dremio, щоб приєднати дані, що знаходяться в MongoDB та Postgres, одним запитом. Обидва мають з'єднувачі для кожної з цих баз даних (див. Документи тут і тут ) і пропонують відповідно запустити "SQL на що завгодно" та "приєднатися до чого завгодно".

Щоб перевірити Presto, ви можете розгорнути невеликий кластер на AWS EMR за допомогою Hadoop, Hive та Presto (додайте відтінок, якщо ви не хочете використовувати командний рядок), він працює з поля - обов'язково дотримуйтесь цих інструкцій для налаштування з'єднувачі . Вулик не є строго необхідним, але з ним, ви можете створювати таблиці , використовуючи результат з з'єднують між Монго і Postgres (перевірити цю сторінку для прикладу). На ринку також є платна версія , яка (нібито) сильно оптимізована і має 30-денний пробний термін .

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.