Мій поточний проект, по суті, є запуском системи управління документами.
Сказане, є деякі зморшки (здивування, здивування). Хоча деякі зморшки досить специфічні для проекту, я вважаю, що виникають деякі загальні спостереження та питання, які не мають канонічної відповіді (що я міг би знайти в будь-якому випадку) і які застосовні до ширшої проблемної області . Тут багато чого, і я не впевнений, що це добре підходить для формату питань 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
стовпчику.