Розуміння обмеження розміру документа MongoDB BSON


153

Від MongoDB Остаточний посібник:

Документи розміром більше 4 Мб (при перетворенні в BSON) не можуть бути збережені в базі даних. Це дещо довільна межа (і може бути підвищена в майбутньому); здебільшого це запобігає поганому проектуванню схеми та забезпечить послідовну продуктивність.

Я не розумію цього обмеження, чи означає це, що Документ, що містить допис у блозі з безліччю коментарів, який просто більший за 4 Мб, не може зберігатися як один документ?

Чи враховує це також вкладені документи?

Що робити, якщо я хотів документ, який перевіряє зміни у значенні. (Врешті-решт це може зрости, перевищивши ліміт 4 Мб.)

Сподіваюся, хтось це правильно пояснить.

Я щойно почав читати про MongoDB (перша база даних nosql, про яку я дізнаюся).

Дякую.


5
Я думаю, що питання повинно уточнити, що це обмеження розмірів збережених документів MongoDB, а не формату BSON.
alexpopescu

2
Хоча я просто спробував зберегти величезний документ, який, безумовно, перевищує 4 МБ, щоб отримати повідомлення "BSON :: InvalidDocument: Документ занадто великий: Документи BSON обмежені 4194304 байтами." Якщо це так, чи не введено це в оману в повідомленні про попередження / помилку?
Nik So

18
Ви можете легко знайти максимальний розмір документа BSON з db.isMaster().maxBsonObjectSize/(1024*1024)+' MB'командою в mongoоболонці.
AhmetB - Google

5
яка мета безсхемового nosql, коли ви не можете скидати записи більш ніж 16 Мбіт і вбудовані грубі операції поверх нього!
Rizwan Patel

Я думаю, що початкова цитата говорить про це все ... Межа встановлена, щоб запобігти поганому дизайну схеми. Наприклад, якщо у вас є публікація з багатьма коментарями, ви хочете колекцію записів у блозі та колекцію коментарів або колекцію змін. Конструкція mongo / nosql дозволяє створювати речі масового розміру як мережі документів, але розробнику потрібно розбити їх на частини, які мають сенс. Якщо обмеження розміру не встановлено, виникнуть інші проблеми. Я думаю, що межа 4mb була чудовою. 16mb, чудово! Але якщо я пишу документ на 16 Мб, це підказка, що з дизайном щось не так.
Вії

Відповіді:


126

По-перше, це насправді піднімається в наступній версії до 8MBабо 16MB... але я думаю, щоб поставити це на перспективу, Еліот з 10gen (який розробив MongoDB) вважає це найкращим:

EDIT: Розмір офіційно "підвищений" до16MB

Отже, на прикладі вашого блогу, 4 Мб - це фактично багато. Наприклад, повний розтиснутий текст "Війни світів" становить лише 364 к (html): http://www.gutenberg.org/etext/36

Якщо ваша публікація в блозі така довга з такими багатьма коментарями, я, наприклад, не збираюся її читати :)

Для зворотних треків, якщо ви виділили їм 1 Мб, ви могли легко отримати більше 10 Кб (можливо, ближче до 20 Кб)

Тож крім справді химерних ситуацій, це буде чудово. І у випадку винятку чи спаму, я дійсно не думаю, що ви хочете, щоб ви хотіли об'єкт 20 Мб. Я думаю, що обмеження трекбеків становить 15 кб або більше має багато сенсу незалежно від продуктивності. Або принаймні спеціальний кожух, якщо він коли-небудь трапиться.

-Еліот

Я думаю, що вам буде досить важко натиснути, щоб досягти межі ... і з часом, якщо ви будете модернізувати ... вам доведеться турбуватися все менше і менше.

Основний пункт обмеження полягає в тому, щоб ви не використовували всю оперативну пам’ять на своєму сервері (так як вам потрібно завантажити всі MBдокументи документа в оперативну пам’ять при запиті.)

Таким чином, обмеження становить деякий% від звичайної корисної оперативної пам’яті в загальній системі… яка буде постійно зростати з року в рік.

Примітка щодо зберігання файлів у MongoDB

Якщо вам потрібно зберігати документи (або файли) більше, ніж 16MBви можете використовувати API GridFS, який автоматично розбиває дані на сегменти та передаватиме вам назад (таким чином, уникаючи проблеми з обмеженням розміру / ОЗУ.)

Замість того, щоб зберігати файл в одному документі, GridFS розділяє файл на частини або фрагменти і зберігає кожен фрагмент як окремий документ.

GridFS використовує дві колекції для зберігання файлів. Один збірник зберігає фрагменти файлів, а інший зберігає метадані файлу.

Ви можете використовувати цей метод для зберігання зображень, файлів, відео тощо в базі даних, наскільки це можливо в базі даних SQL. Я використовував це для навіть збереження мультигабайтних відеофайлів.


2
Це дивовижно, що у вас є достатня кількість оперативної пам’яті для всієї вашої бази даних… Зазвичай «робочий набір» знаходиться в оперативній пам’яті, а не по всій базі даних (як, наприклад, у моєму випадку я маю більше ніж один x ГБ баз даних, де якщо все додане перевищуватиме мою оперативну пам’ять, але це нормально, тому що робочий набір набагато, набагато менший.) Також, якщо не було обмежень, ви можете завантажити 800 МБ документа в оперативну пам’ять з одним запитом і 400 кк з іншим, зробивши балансування оперативної пам’яті трохи складним і т.д. Таким чином, "межа" - це деякий% типової оперативної пам'яті сервера (таким чином, вона зростає з часом.) Mongodb.org/display/DOCS/Checking+Server+Memory+Usage
Джастін Дженкінс

3
Чудово, що ви можете зберігати все в оперативній пам’яті, але враховуйте ефективність та ідіому повідомлення в блозі. Ви, очевидно, хочете, щоб публікація залишалася в пам'яті, якщо її прочитали. Але чи дійсно ви хочете, щоб 10 сторінок коментарів до публікації в блозі залишилися в пам’яті, коли більшість людей ніколи не прочитають повз першу сторінку? Звичайно, ви можете це зробити, і якщо ваша база даних є достатньо малою, щоб вона могла вміститись у пам'яті, то жодних проблем. Але з точки зору чистої ефективності, ви не хочете, щоб марні біти займали простір пам'яті, якщо ви зможете цього уникнути (і це стосується і RDBMS).
AlexGad

50
солодкий Ісусе, тож аргумент Монго: "16 Мб для когось вистачить"? Це не так, як у минулому, виявилося, що воно було неправильним.
Роберт Христос

2
Це здається мені занадто поганим. Монго повинен бути корисним для великих даних, не має таких обмежень. У моєму проекті мені потрібно зібрати та групувати твіти, пов’язані з тією самою тенденційною темою, і це може закінчитися більше ніж 20000 твітами протягом 20 годин часу (і цілком можливо, що тенденції будуть дурити більше, ніж 20 годин в моїй db). Маючи таку кількість твітів і зберігаючи текст одночасно, це руйнівно, і після згрупування кількох невеликих тенденцій це закінчується винятком з великої тенденції.
Савас Парастатидіс

7
@savvas, чому б ти поставив усі твіти в один документ? Використовуйте один документ за твіт, додайте тенденційну тему як інше поле документа. поставити індекс на тематичне поле, а потім об'єднати це поле за допомогою трубопроводу mongo. знадобиться певне коригування того, як ви робите речі для роботи з nosql, як тільки ви налаштуєте свої методи та подумаєте, що ви виявите, що це чудово працює для багатьох випадків використання великих даних.
schmidlop

32

Багато хто в громаді вважають за краще не обмежуватись попередженнями про ефективність, дивіться цей коментар для обґрунтованого аргументу: https://jira.mongodb.org/browse/SERVER-431?focusedCommentId=22283&page=com.atlassian.jira.plugin. system.issuetabpanels: коментар-вкладка # comment-22283

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


5
Я повністю згоден з вами, і це перемагає мету вбудовувати документи зараз, оскільки більшість вбудованих документів тепер легко переступить межу. Esp із масивом документів усередині них
Шарджіл Ахмед

@ marr75 це каже виправлене зараз, це було виправлено?
Мафій

1
Я маю на увазі, ліміт був підвищений до 16 Мб, що не фіксує довгострокову проблему; ІМО ліміт слід просто усунути.
marr75

2
6-річна нитка некро. Я твердо не переконаний вашим конкретним прикладом поганого використання / дизайном. Крім того, цей приклад набагато краще пояснює, чому вам потрібно перевірити дані, ніж обмеження розміру одного документа в базі даних. Зробити додаток розділити свої вкладені документи як окремі документи в іншій колекції або запустити новий документ "продовження" (рішення, які я кілька разів використовував для роботи в межах цієї межі), мало вплинуло на продуктивність, але великий вплив на складність коду. Вся точка БД документа - це локалізація даних.
marr75

4
Дякуємо, що займаєтесь такою ж математикою, як документи mongoDB, щоб захистити це рішення, але ваш окремий випадок використання та продуманий експеримент далеко не переконливий. Мені довелося придумати складні, зайві конструкції, щоб подолати той факт, що існує довільна межа, яка дійсно потрапляє під монго (без глибоко вкладених чи дублюваних записів, btw). За вашою логікою, жодна база даних не повинна містити більше 16 Мб, оскільки деякий довільний текст можна представити, використовуючи менше місця. Це, очевидно, нерозумно.
marr75

31

Тут можна розмістити роз'яснювальну відповідь для тих, кого Google направляє сюди.

Розмір документа включає все в документі, включаючи піддокументи, вкладені об'єкти тощо.

Отже документ:

{
    _id:{},
    na: [1,2,3],
    naa: [
        {w:1,v:2,b:[1,2,3]},
        {w:5,b:2,h:[{d:5,g:7},{}]}
    ]
}

Має максимальний розмір 16meg.

Субудокументи та вкладені об'єкти зараховуються до розміру документа.


За іронією долі, найбільшою можливою структурою, яку можна представити в BSON, є також найбільш компактна. Незважаючи на те, що MongoDB використовує size_t(64-розрядні) індекси масивів всередині, обмеження розміру документа в 16 МБ в кращому випадку зможе представляти документ, що містить сам масив, що містить два мільйони NULL.
amcgregor

Вибачте, додавши другий коментар, щоб вирішити / уточнити ще одну важливу деталь: коли ви говорите, що розмір документа включає все в документі , що також включає ключі . Наприклад {"f": 1}, на два байти менше, ніж {"foo": 1}. Це може швидко скластися, якщо ви не будете обережні, хоча сучасне стискання на диску допомагає.
amcgregor

6

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

JSON - це текстовий формат. Отже, якщо ви отримуєте доступ до своїх даних через JSON, це особливо актуально, якщо у вас є двійкові файли, оскільки вони повинні бути закодовані в uuencode, hexadecimal або Base 64. Шлях конверсії може виглядати як

двійковий файл <> JSON (закодований) <> BSON (закодований)

Було б більш ефективно поставити шлях (URL) до файлу даних у вашому документі та зберегти самі дані у двійковій формі.

Якщо ви дійсно хочете зберегти ці файли невідомої довжини у вашій БД, вам, ймовірно, буде краще розмістити їх у GridFS і не ризикувати вбивати ваші сукупності, коли доступ до великих файлів.


1
"Вже існує різноманітність баз даних, які дуже ефективні для зберігання / отримання великих файлів; їх називають операційними системами."; Дивіться blog.mongodb.org/post/183689081/…
redcalx


2

Можливо зберігання в блозі -> коментарі відносини в НЕ реляційну базу даних насправді не найкращий дизайн.

Ви, ймовірно, повинні зберігати коментарі в окремій колекції до публікацій блогу.

[редагувати]

Дивіться коментарі нижче для подальшого обговорення.


15
Я зовсім не згоден. Коментарі у документах із публікації вашого блогу повинні бути чудовими в MongoDB ... це дуже поширене використання (я використовую це не одне місце у виробництві, і він працює досить добре.)
Джастін Дженкінс,

2
Я був, мабуть, надто суворим у своїй відповіді. Немає нічого поганого в зберіганні публікацій блогів та відповідних коментарів у MongoDB або подібній базі даних. Більше того, люди схильні до надмірного використання баз даних на основі документальних можливостей (найбільш радикальним прикладом може бути зберігання всіх ваших даних в одному документі під назвою "блог")
Mchl,

3
@Mchel: "Щоденник" не годиться, але зберігання коментарів в окремій колекції так само погано з тих же причин. Повідомлення з масивом коментарів - це, наприклад, канонічний приклад документа db.
Метт Бріггс

6
@SoPeople: зберігання коментарів у публікації схоже на канонічний приклад баз даних, орієнтованих на документи. (як-от зберігання цілого тексту вікі всередині одного документа) Якби я писав ТА, він би повністю запускався на MongoDB. Жодна з цих записів SO НЕ буде розумно перевищувати 4МБ. Craigslist робить величезну міграцію БД своєї історії до MongoDB. У них було лише кілька документів, які перейшли цю межу, і провідний розробник припустив, що самі документи фактично розбиті (результат деяких помилок). Знову 4 меги - це кілька романів тексту.
Гейтс ВП

3
@Gates VP, я погоджуюся використовувати окремий повнотекстовий механізм. Я думав про пошук метаданих. Що робити, якщо у вас є комплект книжкових документів, і ви хочете знайти всі книги, видані в 1982 році? Якщо кожна книга має + 100 кб тексту, ви не хочете передати кілька мегабайт лише для відображення перших 20 назв книг.
mikerobi

0

Відповідно до https://www.mongodb.com/blog/post/6-rules-of-thumb-for-mongodb-schema-design-part-1

Якщо ви очікуєте, що публікація в блозі може перевищити ліміт документа на 16 Мбіт, слід витягнути коментарі до окремої колекції та віднести посилання на коментар до коментаря та зробити приєднання на рівні програми.

// posts
[
  {
    _id: ObjectID('AAAA'),
    text: 'a post',
    ...
  }
]

// comments
[
  {
    text: 'a comment'
    post: ObjectID('AAAA')
  },
  {
    text: 'another comment'
    post: ObjectID('AAAA')
  }
]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.