Базы данных документов: избыточные данные, ссылки и т. Д. (В частности, MongoDB) - PullRequest
26 голосов
/ 18 октября 2010

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

Таким образом, простой ответ - сохранить идентификатор пользователя в документе хранилища илиИдентификатор магазина в документе пользователя.Тем не менее, часто требуется доступ к 1-2 другим частям данных для отображения, потому что идентификаторы бесполезны.Как, например, имя клиента или название магазина.

  1. Обычно вы храните дубликат всего документа?Или просто хранить нужные вам данные?Может быть, зависит от размера документа и его количества.
  2. Как вы справляетесь с тем, что у вас есть дубликаты данных?Вы идете выслеживать данные, когда они меняются?Обновлять данные через определенный промежуток времени, когда он загружен?Дублировать только тогда, когда вы можете позволить себе устаревшие данные?

Буду признателен за ваш вклад и / или ссылки на любые виды «передового опыта» или хотя бы обоснованное обсуждение этих тем.

Ответы [ 3 ]

29 голосов
/ 18 октября 2010

Существует в основном два сценария: fresh и stale .

Свежие данные

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

В этом сценарии у вас будут некоторые накладные расходы из-за дополнительных запросов. Альтернативой является отслеживание всех местоположений дубликатов данных и обновление всех экземпляров при каждом обновлении. Это также связано с накладными расходами, особенно в отношениях N-to-M, подобных тому, который вы упомянули. Так или иначе, у вас будут дополнительные издержки, если вам нужны свежие данные. Вы не можете иметь лучшее из обоих миров.

Устаревшие данные

Если вы можете позволить себе устаревшие данные, все становится намного проще. Чтобы избежать лишних запросов, вы можете хранить дубликаты данных. Чтобы избежать необходимости дублирования данных, вы не собираетесь хранить дубликаты данных. По крайней мере, не активно .

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

Основная информация

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

14 голосов
/ 18 октября 2010

Ответ здесь действительно зависит от того, насколько актуальными должны быть ваши данные.

@ Niels имеет хорошее резюме здесь, но я думаю, что справедливо отметить, что вы можете "обмануть".

Допустим, вы хотите отобразить магазины, используемые пользователем. Очевидная проблема здесь заключается в том, что вы не можете «встроить» Магазин в Пользователя, так как Магазин слишком важен сам по себе. Но то, что вы можете сделать, это встроить некоторые Хранить данные в пользователе.

Просто используйте материал, который вы хотите отобразить, например, «Название магазина». Ваш объект User будет выглядеть так:

{
  _id : MongoID(),
  name : "Testy Tester",
  stores : [ 
             { _id : MongoID(), "name" : 'Safeway' },
             { _id : MongoID(), "name" : 'Walmart' },
             { _id : MongoID(), "name" : 'Best Buy' }
            ]
}

Таким образом, вы можете отобразить типичное «сеточное» представление, но для получения дополнительных данных о магазине требуется ссылка.

2 голосов
/ 09 октября 2011

Чтобы ответить на ваши прямые вопросы:

  1. Нет дубликатов.
  2. Нет дубликатов.

;)

Единственные дубликаты, которые вы когда-либо должны иметь, - это «простые» значения, такие как веса (которые могут оказаться одинаковыми, но не эффективнее ни по времени, ни по пространству для хранения отдельно), и идентификаторы, ссылающиеся на другой объект ( являются дублирующими значениями, но они намного меньше и более управляемы, чем дублирующиеся данные объекта, которые они заменяют).

Теперь, чтобы ответить на ваш сценарий: вам нужны отношения «многие ко многим». Обычное решение здесь - создать третью "сквозную" или "мостовую" таблицу / коллекцию, вероятно, называемую StoreUsers:

StoreUsers
----------
storeuser_id
store_id
user_id

Вы добавляете запись к этому для каждой ссылки между магазинами и пользователями, будь то для другого магазина, другого пользователя или группы пользователей в одном магазине. Затем вы можете найти это независимо для магазина или для пользователя. MongoDB также поддерживает этот подход; это не зависит от СУБД.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...