Слишком много дублирования данных в mongodb?

Я новичок во всем этом материале NOSQL и недавно был заинтригован mongoDB. Я создаю новый сайт с нуля и решил пойти с MONGODB/NORM (для С#) в качестве моей единственной базы данных. Я много читал о том, как правильно создать базу данных модели документов, и я думаю, что по большей части у меня хорошо разработан дизайн. Мне около 6 месяцев на новый сайт, и я начинаю видеть проблемы с дублированием/синхронизацией данных, с которыми мне нужно иметь дело снова и снова. Из того, что я читал, это ожидается в модели документа, а для производительности это имеет смысл. И.Е. вы вставляете внедренные объекты в свой документ, чтобы быстро читать - нет соединений; но, конечно, вы не всегда можете вставлять, поэтому mongodb имеет эту концепцию DbReference, которая в основном аналогична внешнему ключу в реляционных БД.

Итак, вот пример: у меня есть пользователи и события; оба получают свой собственный документ, пользователи посещают события, события имеют пользователей. Я решил включить список объектов с ограниченными данными в объекты User. Я включил список "Пользователи" в объекты "Событие" в качестве "участников". Теперь проблема заключается в том, что я должен синхронизировать пользователей со списком пользователей, который также встроен в объект Event. Поскольку я читал это, это, по-видимому, предпочтительный подход, и способ NOSQL делать что-то. Поиск выполняется быстро, но спад - это когда я обновляю основной документ пользователя, мне также нужно пойти в объекты Event, возможно, найти все ссылки на этого пользователя и обновить его.

Итак, вопрос, который у меня есть, - это довольно распространенная проблема, с которой люди должны иметь дело? Насколько эта проблема должна произойти до того, как вы начнете говорить: "Возможно, стратегия NOSQL не подходит для того, что я пытаюсь сделать здесь"? Когда преимущество производительности в том, что вам не нужно делать соединения, превращается в недостаток, потому что вам сложно хранить данные во встроенных объектах и ​​делать несколько записей в БД для этого?

Ответы

Ответ 1

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

У Mongo действительно эффективные индексы, которые упрощают нормализацию, как традиционная RDMS (большинство хранилищ документов не дают вам этого бесплатно, поэтому Mongo скорее гибрид, чем чистый хранилище документов). Используя это, вы можете создать коллекцию отношений между пользователями и событиями. Он аналогичен суррогатной таблице в табличном хранилище данных. Индекс полей событий и пользователей должен быть довольно быстрым и поможет вам нормализовать ваши данные.

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

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

Несколько советов:

  • Если вам требуется быстрый поиск, чтобы быть быстрым и атомарным (совершенно современно), вам может понадобиться услуга, в которой вы предпочитаете выравнивание по нормализации и попадание в обновление.
  • Если вам требуется, чтобы обновление было быстрым, а доступ сразу же стал нормализацией.
  • Если вам требуются быстрые поисковые запросы, но они не требуют совершенно свежих данных, подумайте о том, чтобы построить нормализованные данные в пакетных заданиях (возможно, используя карту/уменьшить).
  • Если ваши запросы должны быть быстрыми, а обновления редки и не обязательно требуют немедленного доступа к вашему обновлению или требуют блокировки уровня транзакции, которая прошла через 100% времени (чтобы гарантировать, что ваше обновление было записано на диск), вы можете рассмотреть возможность записи своих обновлений в очередь, обрабатывая их в фоновом режиме. (В этой модели вам, вероятно, придется столкнуться с разрешением конфликтов и согласованием позже).
  • Профиль разных моделей. Создайте в своем коде слой абстракции запроса данных (например, ORM), чтобы позднее можно было реорганизовать структуру хранилища данных.

Есть много других идей, которые вы можете использовать. Там много замечательных блогов на линии, которые входят в него, как highscalabilty.org, и убедитесь, что вы понимаете теорему CAP.

Также рассмотрите слой кэширования, например Redis или memcache. Я поставлю один из этих продуктов перед своим слоем данных. Когда я запрашиваю mongo (который сохраняет все нормализованное), я использую данные для построения сплющенного представления и сохранения его в кеше. Когда я обновляю данные, я аннулирую любые данные в кеше, которые ссылаются на то, что я обновляю. (Хотя вам необходимо потратить время, чтобы аннулировать данные и данные отслеживания в кэше, который обновляется с учетом ваших коэффициентов масштабирования). Кто-то однажды сказал: "Две самые трудные вещи в" Компьютерной науке "называют и недействительными кэш-памяти".

Надеюсь, что это поможет!

Ответ 2

Попробуйте добавить к объекту User объект IList типа UserEvent. Вы не указали многое о том, как разработана модель вашего домена. Проверьте группу NoRM http://groups.google.com/group/norm-mongodb/topics для примеров.

Ответ 3

В 1Schema.com мы пытаемся решить именно эту проблему!

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

С этой целью мы проводим различие между "реальными данными" (фактически существует внутри документа) и "кэшированными данными" (существует вне документа, но скопировано локально)

Обновление "реальных данных" в документе заставляет автоматически обновлять все свои кешированные копии.

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

С этой целью мы используем разные типы ребер для обозначения разных типов поведения:

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

"Ключ внешнего ключа" определяет, как другие документы кэшируются локально в пределах заданного документа на основе ссылок на идентификаторы (кросс-агрегированные ссылки в DDD)

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

Пожалуйста, проверьте наш экспорт в MongoDB, чтобы узнать, как мы автоматизируем распространение изменений... весь экспортированный код работает в оболочке Mongo, нет необходимости в специальных библиотеках