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