2016-05-26 7 views
2

Итак, у меня есть немного данных о многих людях в компании, таких как их имена, возраст и пол. Я собираюсь хранить их информацию в MongoDB. Будет ли лучше хранить информацию в большом количестве документов или в одном документе как кучу отдельных объектов? Есть ли проблемы с производительностью или памятью, которые сделают один метод выше другого?Лучше использовать документ с большим количеством объектов или просто с большим количеством документов?

Пример способы хранения данных:

Много документов

{ 
    _id: ObjectId('1'), 
    name: 'Bart', 
    age: 10, 
    gender: 'Male' 
}, 
{ 
    _id: ObjectId('2'), 
    name: 'Lisa', 
    age: 8, 
    gender: 'Female' 
} 

Много объектов в одном документе

{ 
    _id: ObjectId('1'), 
    'Bart': { 
    age: 10, 
    gender: 'Male' 
    }, 
    'Lisa': { 
    age: 8, 
    gender: 'Female' 
    } 
} 

Для тех, кто интересно, я бы запросите второй пример с помощью Монго параметр проекции, например.

db.families.find({_id:ObjectId('1')},{_id:0,'Bart':1}); 

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

+0

первый один хороший. (много документов), becoz «второй» может возникнуть проблема с памятью, и вы не можете создать индекс в большем поле, имя объекта becoz является динамическим (Bart, Lisa), а также сортировать также can not do ect .. мое предложение первое один лучший – karthi

ответ

4

Первый предпочтительный.

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

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

Если вы намерены иметь несколько компаний с пользователями, вы можете либо использовать отдельную коллекцию для каждого, либо добавить атрибут компании в документ. Это зависит от того, сколько компаний вы собираетесь поддерживать, но при условии, что это будет не просто 2 или 3, я бы предпочел последний вариант. Его легче поддерживать, масштабировать (т. Е. Ошпаривать), оптимизировать (индексы и т. Д.) Или расширять.

{ 
    _id: ObjectId('1'), 
    name: 'Bart', 
    age: 10, 
    gender: 'Male' 
    company: 'XYZ' 
} 

Edit:

еще несколько соображений относительно производительности.Основной поток событий для обоих вариантов является следующее:

1-док стратегии (с выступом)

  1. найти документ по ObjectId, используя индекс (в памяти) быстрое
  2. погрузка весь документ (от DICS) в зависимости от размера документа, может быть медленным
  3. проекции (в памяти) быстрое

стратегия п-док (без проекции)

  1. находки документа по ObjectId или именем, используя индекс (в памяти), быстрый
  2. загрузка (маленький) документа с диска, медленно, но быстрее, чем загрузка больших документов

Специально для стратегии 1-doc может возникнуть переломный момент, когда он становится медленнее, чем стратегия n-doc, особенно когда документ растет. Для небольших документов он может быть равен или, может быть, быстрее, особенно когда происходит кеширование или возникают другие случаи ребер (т. Е. Диапазон имен ограничен, что делает запросы для имен не очень избирательными, но в этом случае вы были бы прикручены 1-док подход в любом случае)

рекомендация Mongo для проектирования схемы заключаются в следующем:

  • 1: 1 соотношение: использование встроенных документов
  • 1: несколько отношений: использование встроенных документов
  • 1: многие использование нескольких коллекций

Что вы намерены делать, так это иметь отношения компании: человека, которое может быть третьим или вторым вариантом. Так что либо у вас есть две коллекции:

  • компании
  • лиц (внешний ключ к компании)

или

  • компании (с лицами, внедренных)

либо Кстати, я бы моделировал человека как

person: 
{ 
    _id: ObjectId('1'), 
    name: 'Bart', 
    age: 10, 
    gender: 'Male' 
    company: 'XYZ' //only for foreign key relationship to separate collection 
} 

В случае встроенного человека, было бы массив в компании

company: 
{ 
    name: 'companyA', 
    persons: [..] //and not use person's name as key here 
} 

Я могу добавить индекс persons.name и/или company. Таким образом, поиск одного человека выполняется полностью в памяти (с использованием индекса), и загрузка документа человека должна быть быстрой, так как только маленький документ считывается с диска.

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

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

  • вы не можете иметь индексы на людей
  • вам требуется дополнительная логика приложения, если документы растут за 16Мб (что в конечном итоге может случиться)
  • вы не можете иметь дело с теми же именами (что может произойти)
  • вы менее гибки (изменяете схемы, выбираете атомарность операции обновления в распределенной среде, добавляете дополнительные шаблоны доступа, такие как перечисление всех лиц компании)
  • Техническое обслуживание может стать громоздким (вам необходимо изучить документы компании, чтобы найти имена людей)
  • могут возникнуть побочные эффекты для осколков или репликации, о которых я и не думал сейчас
  • это нарушает принципы дизайна оо (вопрос себя: это «Барт» - собственность семьи или «сына» или, дети ") - что делает его менее ремонтопригодны тоже

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

+0

Спасибо за очень подробный ответ. Пара вещей, я не буду бить лимит 16 МБ с моими данными, мне не нужно сложное сопоставление, так как я буду знать имена перед запросом на них. Это отличная точка для обновления, но что-то ищет через индекс, а просто с помощью проецирования на самом деле быстрее? вы могли бы дать контрольный показатель? –

+0

Это зависит: возможно, это довольно быстро, используя findInd и проекцию, потому что есть индекс на objectId. Если вы не знаете идентификатор объекта и должны искать имя, индекс имени будет лучше, особенно для больших коллекций. Как сказано, дизайн схемы зависит от шаблона доступа вашего приложения. Возможно, для вашего конкретного случая использование одного документа было бы неплохо, но в целом я не буду этого делать, особенно используя значения (имена) в качестве ключей - хороший источник серьезных головных болей;) –

+0

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