Comprensione del limite della dimensione del documento MongoDB BSON


153

Da MongoDB La guida definitiva:

I documenti di dimensioni superiori a 4 MB (quando convertiti in BSON) non possono essere salvati nel database. Questo è un limite un po 'arbitrario (e potrebbe essere aumentato in futuro); è principalmente per prevenire la cattiva progettazione dello schema e garantire prestazioni costanti.

Non capisco questo limite, questo significa che un documento contenente un post sul blog con molti commenti che in questo caso supera i 4 MB non può essere archiviato come un singolo documento?

Anche questo conta anche i documenti nidificati?

E se volessi un documento che controlla le modifiche a un valore. (Alla fine potrebbe crescere, superando il limite di 4 MB.)

Spero che qualcuno lo spieghi correttamente.

Ho appena iniziato a leggere su MongoDB (primo database nosql di cui sto imparando).

Grazie.


5
Penso che la domanda dovrebbe chiarire che si tratta di una limitazione delle dimensioni dei documenti archiviati MongoDB e non del formato BSON.
alexpopescu,

2
Tuttavia, ho appena provato a salvare un documento enorme che sicuramente supera i 4 MB per ottenere il messaggio "BSON :: InvalidDocument: documento troppo grande: i documenti BSON sono limitati a 4194304 byte". In tal caso, non è forse fuorviante nel messaggio di avviso / errore?
Nik So,

18
È possibile trovare facilmente la dimensione massima del documento BSON con il db.isMaster().maxBsonObjectSize/(1024*1024)+' MB'comando nella mongoshell.
AhmetB - Google,

5
qual è lo scopo del nosql schematico in cui non è possibile eseguire il dump di record più di 16 mb e ha creato un'operazione grezza su di esso!
Rizwan Patel,

Penso che la citazione iniziale dica tutto ... Il limite è in atto per prevenire una cattiva progettazione dello schema. Se, ad esempio, hai un post con molti commenti, desideri una raccolta di post di blog e una raccolta di commenti o una raccolta di modifiche. Il design di mongo / nosql consente di realizzare oggetti di dimensioni massime come reti di documenti, ma lo sviluppatore deve dividerli in parti sensate. Se non viene impostato alcun limite di dimensione, si verificheranno altri problemi. Penso che il limite di 4 MB andasse bene. 16mb, fantastico! Ma se sto scrivendo un documento da 16 MB, è un indizio che qualcos'altro non va nel design.
Ciglia

Risposte:


126

Prima di tutto, questo in realtà viene sollevato nella prossima versione di 8MBo 16MB... ma penso di metterlo in prospettiva, Eliot di 10gen (che ha sviluppato MongoDB) lo mette meglio:

EDIT: la dimensione è stata ufficialmente "aumentata" a16MB

Quindi, nell'esempio del tuo blog, 4 MB sono in realtà un sacco ... Ad esempio, il testo completo non compresso di "War of the Worlds" è solo 364k (html): http://www.gutenberg.org/etext/36

Se il tuo post sul blog è così lungo con così tanti commenti, io per primo non lo leggerò :)

Per i trackback, se hai dedicato 1 MB a loro, potresti facilmente avere più di 10k (probabilmente più vicino a 20k)

Quindi, tranne per le situazioni davvero bizzarre, funzionerà alla grande. E nel caso dell'eccezione o dello spam, non credo davvero che vorresti comunque un oggetto da 20 MB. Penso che limitare i trackback come 15k o giù di lì abbia molto senso, non importa quale sia per le prestazioni. O almeno involucro speciale se mai dovesse succedere.

-Eliot

Penso che saresti abbastanza difficile raggiungere il limite ... e col tempo, se aggiorni ... dovrai preoccuparti sempre meno.

Il punto principale del limite è quindi di non utilizzare tutta la RAM sul server (poiché è necessario caricare tutti i messaggi MBs nella RAM durante la query).

Quindi il limite è un po 'della normale RAM utilizzabile su un sistema comune ... che continuerà a crescere anno dopo anno.

Nota sulla memorizzazione di file in MongoDB

Se è necessario archiviare documenti (o file) di dimensioni superiori 16MBa quelle disponibili, è possibile utilizzare l' API GridFS che suddividerà automaticamente i dati in segmenti e li trasmetterà di nuovo a voi (evitando così il problema con limiti di dimensioni / RAM).

Invece di archiviare un file in un singolo documento, GridFS divide il file in parti o blocchi e memorizza ogni blocco come documento separato.

GridFS utilizza due raccolte per archiviare i file. Una raccolta memorizza i blocchi di file e l'altra memorizza i metadati dei file.

È possibile utilizzare questo metodo per archiviare immagini, file, video, ecc. Nel database, proprio come si farebbe in un database SQL. L'ho usato anche per archiviare file video multi gigabyte.


2
È fantastico avere abbastanza RAM per l'intero database ... In genere il "working set" è nella RAM, non nell'intero database (come nel mio caso ho più di un database x GBs dove se tutto sommato superasse la mia RAM, ma va bene perché il set di lavoro è molto, molto più piccolo.) Inoltre, se non ci fosse limite potresti caricare un documento da 800 MB nella RAM con una query e un documento da 400k con un altro, rendendo un po 'difficile il bilanciamento della RAM, ecc. Quindi il "limite" è un po 'della tipica RAM del server (quindi cresce nel tempo). Mongodb.org/display/DOCS/Checking+Server+Memory+Usage
Justin Jenkins

3
È fantastico poter archiviare tutto nella RAM, ma considera l'efficienza e il linguaggio dei post sul blog. Ovviamente vuoi che un post sia in memoria se viene letto. Ma vuoi davvero 10 pagine di commenti per un post di blog in memoria quando la maggior parte delle persone non leggerà mai oltre la prima pagina? Certo, puoi farlo e se il tuo database è abbastanza piccolo da poter stare tutto in memoria, allora nessun problema. Ma in termini di pura efficienza, non si desidera che bit inutili occupino spazio di memoria se è possibile evitarlo (e questo vale anche per RDBMS).
AlexGad,

50
dolce Gesù, quindi l'argomento di Mongo è "16 MB dovrebbero essere sufficienti per chiunque"? Non è che in passato si sia mai dimostrato errato.
Robert Christ,

2
Questo sembra troppo male per me. Mongo dovrebbe essere utile per i big data, non avere tali limiti. Nel mio progetto, ho bisogno di aggregare e raggruppare i tweet correlati allo stesso argomento di tendenza, e questo potrebbe finire in più di 20000 tweet per un periodo di 20 ore (ed è del tutto possibile che ci saranno tendenze che durano più di 20 ore nel mio db). Avere tanti tweet e archiviare il loro testo allo stesso tempo è devastante e dopo aver raggruppato alcune piccole tendenze, finisce con l'eccezione di una grande tendenza.
Savvas Parastatidis,

7
@savvas perché dovresti mettere tutti i tweet in un unico documento? Usa un documento per tweet, inserisci l'argomento di tendenza come un altro campo nel documento. inserire un indice su quel campo argomento e quindi aggregare su quel campo usando la pipeline mongo. ci vuole un po 'di adattamento su come fare le cose per lavorare con nosql, una volta adeguati i metodi e pensando di trovare che funziona alla grande per molti casi di utilizzo di big data.
schmidlop,

32

Molti nella comunità preferirebbero nessun limite con avvertimenti sulle prestazioni, vedi questo commento per un argomento ben ragionato: https://jira.mongodb.org/browse/SERVER-431?focusedCommentId=22283&page=com.atlassian.jira.plugin. system.issuetabpanels: commento-tabpanel # comment-22283

La mia opinione è che gli sviluppatori principali sono testardi su questo problema perché hanno deciso che era una "caratteristica" importante all'inizio. Non lo cambieranno presto perché i loro sentimenti sono feriti e qualcuno l'ha messo in discussione. Un altro esempio di personalità e politica che toglie un prodotto nelle comunità open source ma questo non è davvero un problema paralizzante.


5
Sono totalmente d'accordo con te, inoltre vanifica lo scopo di avere documenti incorporati ora, poiché la maggior parte dei documenti incorporati ora supererà facilmente il limite. Esp con una serie di documenti al loro interno
Sharjeel Ahmed,

@ marr75 dice riparato ora, è stato riparato?
Mafii,

1
Voglio dire, il limite è stato portato a 16 MB, il che non risolve il "problema" a lungo termine; IMO il limite dovrebbe essere semplicemente eliminato.
marr75,

2
Discussione necro di 6 anni. Non sono fermamente convinto dal tuo specifico caso di cattivo uso / esempio di progettazione. Inoltre, questo esempio è molto più efficace nell'illustrare perché è necessario convalidare gli input piuttosto che avere un limite per le dimensioni del documento singolo del database. Fare in modo che l'applicazione dividesse i suoi documenti nidificati come singoli documenti in un'altra raccolta o avviare un nuovo documento di "continuazione" (soluzioni che ho usato più volte per lavorare entro questo limite) ha avuto un impatto limitato sulle prestazioni ma impatti sulla complessità del codice. L'intero punto dei DB dei documenti è la localizzazione dei dati.
marr75,

4
Grazie per aver fatto la stessa matematica dei documenti mongoDB per difendere questa decisione, ma il tuo caso monouso e l'esperimento mentale sono tutt'altro che conclusivi. Ho dovuto elaborare progetti complessi e ridondanti per ovviare al fatto che esiste un limite arbitrario che viene colpito da Mongo (senza voci profondamente nidificate o duplicate, tra l'altro). Secondo la tua logica, nessun database dovrebbe contenere più di 16 MB in totale perché un testo arbitrario può essere rappresentato usando meno spazio di archiviazione. Questo è ovviamente sciocco.
marr75,

31

Per pubblicare una risposta di chiarimento qui per coloro che vengono indirizzati qui da Google.

Le dimensioni del documento includono tutto il documento inclusi i documenti secondari, gli oggetti nidificati ecc.

Quindi un documento di:

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

Ha una dimensione massima di 16meg.

Sbudocumenti e oggetti nidificati vengono tutti conteggiati in base alle dimensioni del documento.


La più grande struttura possibile che possa essere rappresentata in BSON è, ironicamente, anche la più compatta. Nonostante il fatto che MongoDB utilizzi size_tinternamente indici di array (64 bit), il limite di dimensioni del documento di 16 MB sarebbe, nella migliore delle ipotesi, in grado di rappresentare un documento contenente un singolo array stesso contenente due milioni di NULL.
amcgregor,

Mi scuso, aggiungendo un secondo commento per indirizzare / chiarire un altro dettaglio importante: quando dici che la dimensione del documento include tutto nel documento , che include anche le chiavi . Ad esempio {"f": 1}è due byte più piccolo di {"foo": 1}. Questo può aggiungere rapidamente se non stai attento, anche se la compressione su disco moderna aiuta.
amcgregor,

6

Non ho ancora visto un problema con il limite che non comportava file di grandi dimensioni memorizzati nel documento stesso. Esistono già una varietà di database molto efficienti nell'archiviazione / recupero di file di grandi dimensioni; sono chiamati sistemi operativi. Il database esiste come layer sul sistema operativo. Se si utilizza una soluzione NoSQL per motivi di prestazioni, perché aggiungere un ulteriore sovraccarico di elaborazione all'accesso dei dati inserendo il livello DB tra l'applicazione e i dati?

JSON è un formato di testo. Quindi, se stai accedendo ai tuoi dati tramite JSON, questo è particolarmente vero se hai file binari perché devono essere codificati in uuencode, esadecimale o Base 64. Il percorso di conversione potrebbe apparire come

file binario <> JSON (codificato) <> BSON (codificato)

Sarebbe più efficiente inserire il percorso (URL) nel file di dati nel documento e mantenere i dati stessi in binario.

Se vuoi davvero mantenere questi file di lunghezza sconosciuta nel tuo DB, probabilmente sarebbe meglio metterli in GridFS e non rischiare di uccidere la tua concorrenza quando si accede a file di grandi dimensioni.


1
"Esistono già diversi database che sono molto efficienti nell'archiviazione / recupero di file di grandi dimensioni; sono chiamati sistemi operativi."; Vedi blog.mongodb.org/post/183689081/…
redcalx il


2

Forse memorizzare un post sul blog -> relazione di commenti in un database non relazionale non è proprio il miglior design.

Probabilmente dovresti comunque archiviare i commenti in una raccolta separata per pubblicare post sul blog.

[modificare]

Vedi i commenti qui sotto per ulteriori discussioni.


15
Non sono affatto d'accordo. I commenti nei documenti dei tuoi post sul blog dovrebbero andare perfettamente bene in MongoDB ... è un uso molto comune (lo uso più di un posto in produzione e funziona abbastanza bene.)
Justin Jenkins,

2
Forse ero troppo severo nella mia risposta. Non c'è niente di sbagliato nella memorizzazione dei post del blog e dei commenti associati in MongoDB o database simili. È più che le persone tendono ad abusare delle capacità fornite dai database basati sui documenti (l'esempio più radicale sarebbe quello di archiviare tutti i dati in un singolo documento chiamato "blog")
Mchl,

3
@Mchel: "blog" non è buono, ma archiviare i commenti in una raccolta separata è altrettanto male per gli stessi motivi. I post con un array di commenti sono come, l'esempio cannonico di un documento db.
Matt Briggs,

6
@SoPeople: la memorizzazione dei commenti all'interno di un post è come l'esempio canonico dei DB orientati ai documenti. (come memorizzare l'intero testo di un wiki all'interno di un documento) Se dovessi scrivere SO, funzionerebbe completamente su MongoDB. Nessuna di queste voci SO supererà ragionevolmente 4 MB. Craigslist sta eseguendo una gigantesca migrazione dei DB della sua storia a MongoDB. Avevano solo un paio di documenti che superavano quel limite e lo sviluppatore principale ha suggerito che i documenti stessi fossero effettivamente eliminati (il risultato di alcuni bug). Ancora una volta, 4 mega sono diversi romanzi di testo.
Gates VP

3
@Gates VP, sono d'accordo sull'utilizzo di un motore di testo completo separato. Stavo pensando a una ricerca di metadati. Che cosa succede se si dispone di una serie di documenti del libro e si desidera trovare tutti i libri pubblicati nel 1982? Se ogni libro ha + 100kb di testo, non si desidera trasferire diversi megabyte solo per visualizzare i primi 20 titoli del libro.
mikerobi,

0

Secondo https://www.mongodb.com/blog/post/6-rules-of-thumb-for-mongodb-schema-design-part-1

Se ti aspetti che un post sul blog possa superare il limite del documento di 16 Mb, devi estrarre i commenti in una raccolta separata e fare riferimento al post del blog dal commento ed eseguire un join a livello di applicazione.

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

// comments
[
  {
    text: 'a comment'
    post: ObjectID('AAAA')
  },
  {
    text: 'another comment'
    post: ObjectID('AAAA')
  }
]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.