Дизайн схемы MongoDB - Многие небольшие документы или меньше крупных документов?

Фон
Я прототипирую преобразование из нашей базы данных РСУБД в 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, которые помогли бы мне ответить на мой вопрос.

Ответ 1

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

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

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

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

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

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

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

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

Ответ 2

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

От Лучшие рекомендации для MongoDB:

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

Из 6 правил большого пальца для схемы схемы MongoDB: часть 1:

Моделирование один-на-один

Примером "один-к-немногу" может быть адрес для человека. Эта является хорошим вариантом для внедрения - youd помещает адреса в массив внутри вашего объекта Person.

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

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

Индивидуального Squillions

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

Ответ 3

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

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

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

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

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

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

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

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

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