Слишком много дублирования данных в mongodb? - PullRequest
69 голосов
/ 24 октября 2010

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

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

Так что вопросУ меня есть, это довольно распространенная проблема, с которой люди должны иметь дело?Сколько должно произойти этой проблемы, прежде чем вы начнете говорить «возможно, стратегия NOSQL не соответствует тому, что я пытаюсь сделать здесь»?Когда преимущество в производительности от отсутствия объединений превращается в недостаток, потому что вам трудно синхронизировать данные во встроенных объектах и ​​выполнять несколько операций чтения в БД для этого?

Ответы [ 2 ]

57 голосов
/ 25 октября 2010

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

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

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

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

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

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

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

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

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

0 голосов
/ 25 октября 2010

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

...