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


88

Довідкова інформація
Я прототипую перетворення з нашої бази даних СУБД в MongoDB. Денормалізуючи, здається, ніби я маю два варіанти: один, який призводить до багатьох (мільйонів) менших документів, або той, що веде до меншої кількості (сотні тисяч) великих документів.

Якби я міг перегнати його до простого аналога, це була б різниця між колекцією з меншою кількістю документів Клієнта, подібних до цього (на Java):

клас Клієнт {
    ім'я приватного рядка;
    приватна адреса;
    // кожна CreditCard має сотні екземплярів платежів
    приватний набір кредитних карток <CreditCard>;
}

або колекція з багатьма, багатьма платіжними документами, як це:

клас Оплата {
    приватний замовник;
    приватна CreditCard CreditCard;
    приватна дата оплати дати;
    private float payAmount;
}

Запитання
Чи призначений MongoDB для того, щоб віддавати перевагу багатьом, багатьом дрібним документам або меншій кількості великих документів? Чи здебільшого відповідь залежить від того, які запити я планую виконати? (тобто скільки кредитних карток має клієнт X? проти Якої середньої суми сплатили всі клієнти минулого місяця?)

Я багато оглядався, але не натрапляв на жодну найкращу практику схеми MongoDB, яка допомогла б мені відповісти на моє запитання.

Відповіді:


82

Вам точно потрібно буде оптимізувати для запитів, які ви робите.

Ось моє найкраще здогадування на основі вашого опису.

Ви, мабуть, захочете знати всі кредитні картки для кожного Клієнта, тому зберігайте масив із них у Об’єкті Клієнта. Ви також, мабуть, захочете мати довідку клієнта для кожного платежу. Це дозволить зберегти платіжний документ відносно невеликим.

Об'єкт платежу автоматично матиме власний ідентифікатор та індекс. Можливо, ви також захочете додати індекс до довідки клієнта.

Це дозволить вам швидко шукати платежі за замовником, не зберігаючи кожен об'єкт клієнта щоразу.

Якщо ви хочете відповісти на такі запитання "Якою була середня сума, яку всі клієнти заплатили минулого місяця", ви натомість хочете отримати карту / зменшити для будь-якого значного набору даних. Ви не отримуєте цієї відповіді "в реальному часі". Ви побачите, що зберігання "посилання" на Клієнта, мабуть, досить добре для цих зменшень на карті.

Отже, щоб відповісти прямо на ваше запитання: чи призначений MongoDB віддавати перевагу багатьом, багатьом дрібним документам чи меншій кількості великих документів?

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


30

Згідно з власною документацією MongoDB, схоже, вона розроблена для багатьох дрібних документів.

З найкращих практик щодо ефективності для MongoDB :

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

З 6 правил великого пальця для проектування схеми MongoDB: Частина 1 :

Моделювання один до небагатьох

Прикладом "один до кількох" можуть бути адреси людини. Це хороший варіант використання для вбудовування - ви б розмістили адреси в масиві всередині вашого об'єкта Person.

Один до багатьох

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

Один-до-Скільйонів

Прикладом “один до сквільйонів” може бути система реєстрації подій, яка збирає повідомлення журналу для різних машин. Будь-який хост може генерувати достатньо повідомлень, щоб переповнити розмір документа 16 МБ, навіть якщо все, що ви зберігаєте в масиві, було ObjectID. Це класичний випадок використання “посилання на батьків” - у вас буде документ для хоста, а потім збережеться ObjectID хосту в документах для повідомлень журналу.


11

Документи, які суттєво зростають, можуть зачекати бомби сповільненої дії. Пропускна здатність мережі та використання оперативної пам’яті, ймовірно, стануть вимірними вузькими місцями, що змусить вас починати спочатку.

Спочатку розглянемо дві колекції: Клієнтська та Платіжна. Таким чином, зерно досить невелике: один документ на оплату.

Далі ви повинні вирішити, як змоделювати інформацію про рахунок, наприклад, кредитні картки. Давайте розглянемо, чи містять документи клієнтів масиви інформації про рахунок, чи вам потрібна нова колекція рахунків.

Якщо документи облікового запису відокремлені від документів клієнта, завантаження всіх облікових записів одного клієнта в пам’ять вимагає отримання декількох документів. Це може призвести до додаткової пам'яті, вводу-виводу, пропускної здатності та використання центрального процесора. Чи означає це відразу, що збір рахунків є поганою ідеєю?

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

Чи міг би платіжний документ насправді містити всі платежі, здійснені за встановлений термін (наприклад, день?). Така складність вплине на весь код, який читає та пише платіжні документи. Передчасна оптимізація може бути смертельною для проектів.

Як і документи з рахунку, на платежі легко посилатися, якщо платіжний документ містить лише один платіж. Новий тип документа, наприклад, кредит, може посилатися на платіж. Але чи створили б Ви колекцію кредитів чи вклали б інформацію про кредит до платіжної інформації? Що станеться, якщо згодом вам доведеться вказати кредит?

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

Я хотів би почути про ваші висновки. Удачі!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.