Разработка схемы MongoDB - много маленьких документов или меньше больших документов? - PullRequest
75 голосов
/ 14 июня 2010

Фон
Я создаю прототип преобразования нашей базы данных RDBMS в MongoDB. При денормализации мне кажется, что у меня есть два варианта, один из которых приводит ко многим (миллионам) меньших по размеру документов, а другой - к меньшему (сотни тысяч) больших документов.

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

class Customer {
    private String name;
    private Address address;
    // each CreditCard has hundreds of Payment instances
    private Set<CreditCard> creditCards;
}

или коллекция со многими, многими платежными документами, такими как:

class Payment {
    private Customer customer;
    private CreditCard creditCard;
    private Date payDate;
    private float payAmount;
}

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

Я много осматривался, но не сталкивался с лучшими практиками схемы MongoDB, которые помогли бы мне ответить на мой вопрос.

Ответы [ 3 ]

77 голосов
/ 22 июня 2010

Вам определенно нужно оптимизировать запросы, которые вы делаете.

Вот мое лучшее предположение, основанное на вашем описании.

Возможно, вы захотите знать все кредитные карты для каждого клиента, поэтому храните их в объекте клиента. Вы также, вероятно, захотите иметь ссылку на клиента для каждого платежа. Это позволит сохранить платежный документ относительно небольшим.

Платежный объект автоматически будет иметь свой собственный идентификатор и индекс. Возможно, вы также захотите добавить индекс для ссылки на клиента.

Это позволит вам быстро искать платежи по клиенту, не сохраняя каждый раз объект клиента.

Если вы хотите ответить на такие вопросы, как «Какова средняя сумма, которую все клиенты заплатили в прошлом месяце» вместо этого вы захотите карту / сокращение для любого значительного набора данных. Вы не получаете этот ответ в режиме реального времени. Вы обнаружите, что хранение «ссылки» на Customer, вероятно, достаточно хорошо для этих сокращений карты.

Итак, чтобы ответить на ваш вопрос напрямую: Предназначена ли MongoDB для того, чтобы отдавать предпочтение множеству мелких документов или меньшему количеству больших документов?

MongoDB предназначен для очень быстрого поиска проиндексированных записей. MongoDB очень хорошо находит несколько игл в большом стоге сена. MongoDB не очень хорошо находит большинство иголок в стоге сена. Поэтому постройте свои данные в соответствии с вашими наиболее распространенными вариантами использования и напишите карту / уменьшите количество заданий для более редких вариантов использования.

18 голосов
/ 13 мая 2016

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

Из Рекомендации по повышению производительности для MongoDB :

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

Из 6 Практических правил для схемы схемы MongoDB: Часть 1 :

Моделирование от одного до нескольких

Примером «один к немногим» могут быть адреса человека. это хороший вариант использования для встраивания - вы бы поместили адреса в массив внутри вашего объекта Person.

Один-ко-многим

Примером «один ко многим» могут быть детали для продукта в система заказа запасных частей. Каждый продукт может иметь до нескольких сто запасных частей, но не более пары тысяч или так. Это хороший вариант использования для ссылки - вы бы указали ObjectID части в массиве в документе продукта.

Индивидуальный Squillions

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

8 голосов
/ 18 апреля 2014

Документы, которые со временем существенно растут, могут быть бомбами замедленного действия. Пропускная способность сети и использование ОЗУ, вероятно, станут измеримыми узкими местами, заставляя вас начинать все сначала.

Сначала рассмотрим две коллекции: Customer и Payment. Таким образом, зерно довольно мало: один документ за платеж.

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

Если документы учетной записи отделены от документов клиента, загрузка всех учетных записей одного клиента в память требует загрузки нескольких документов. Это может привести к дополнительной памяти, вводу / выводу, пропускной способности и использованию процессора. Означает ли это, что сбор учетных записей - плохая идея?

Ваше решение влияет на платежные документы. Если информация об учетной записи встроена в документ клиента, как бы вы на нее ссылались? Отдельные документы счета имеют собственный атрибут _id. С помощью встроенной информации об учетной записи ваше приложение будет либо создавать новые идентификаторы для учетных записей, либо использовать атрибуты учетной записи (например, номер учетной записи) для ключа.

Может ли платежный документ фактически содержать все платежи, сделанные в установленные сроки (например, в день?). Такая сложность повлияет на весь код, который читает и пишет платежные документы. Преждевременная оптимизация может быть смертельной для проектов.

Как и документы счета, ссылки на платежи легко ссылаться, если платежный документ содержит только один платеж. Новый тип документа, например кредит, может ссылаться на платеж. Но создадите ли вы Кредитную коллекцию или вы вставите кредитную информацию в платежную информацию? Что произойдет, если вам позже понадобится ссылка на кредит?

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

Мне бы очень хотелось услышать о ваших выводах. Удачи!

...