Comprendre la limite de taille de document MongoDB BSON

153

De MongoDB The Definitive Guide:

Les documents de plus de 4 Mo (lorsqu'ils sont convertis en BSON) ne peuvent pas être enregistrés dans la base de données. C'est une limite quelque peu arbitraire (et peut être augmentée à l'avenir); il s'agit principalement d'éviter une mauvaise conception de schéma et d'assurer des performances constantes.

Je ne comprends pas cette limite, cela signifie-t-il qu'un document contenant un article de blog avec beaucoup de commentaires qui se trouve être plus grand que 4 Mo ne peut pas être stocké en tant que document unique?

Cela compte-t-il également les documents imbriqués?

Et si je voulais un document qui vérifie les changements d'une valeur. (Il finira par grandir, dépassant la limite de 4 Mo.)

J'espère que quelqu'un explique cela correctement.

Je viens de commencer à lire sur MongoDB (première base de données nosql que j'apprends).

Je vous remercie.

Saint
la source
5
Je pense que la question devrait clarifier qu'il s'agit d'une limitation de la taille des documents stockés MongoDB et non du format BSON.
alexpopescu
2
Cependant, j'ai juste essayé d'enregistrer un énorme document qui dépasse très certainement 4 Mo pour obtenir le message "BSON :: InvalidDocument: Document too large: BSON documents are limited to 4194304 bytes." Si tel est le cas, n'est-ce pas un peu trompeur dans le message d'avertissement / d'erreur?
Nik So
18
Vous pouvez facilement trouver la taille maximale de votre document BSON avec la db.isMaster().maxBsonObjectSize/(1024*1024)+' MB'commande dans le mongoshell.
AhmetB - Google
5
quel est le but de schemaless nosql où vous ne pouvez pas vider les enregistrements de plus de 16 Mo et construit une opération crud par-dessus!
Rizwan Patel
Je pense que la citation initiale dit tout ... La limite est en place pour éviter une mauvaise conception de schéma. Si, par exemple, vous avez un article avec de nombreux commentaires, vous voudriez une collection d'entrées de blog et une collection de commentaires, ou une collection de modifications. La conception de mongo / nosql permet des choses de grande taille en tant que réseaux de documents, mais le développeur doit les diviser en parties qui ont du sens. Si aucune limite de taille n'est définie, d'autres problèmes se produiront. Je pense que la limite de 4 Mo était bien. 16 Mo, super! Mais si j'écris un document de 16 Mo, c'est un indice que quelque chose d'autre ne va pas avec la conception.
Cils

Réponses:

126

Tout d'abord, cela est en fait soulevé dans la prochaine version de 8MBou 16MB... mais je pense que pour mettre cela en perspective, Eliot de 10gen (qui a développé MongoDB) le dit le mieux:

EDIT: La taille a été officiellement `` augmentée '' à16MB

Donc, sur votre exemple de blog, 4 Mo, c'est en fait beaucoup. Par exemple, le texte intégral non compressé de "War of the Worlds" ne fait que 364k (html): http://www.gutenberg.org/etext/36

Si votre article de blog est aussi long avec autant de commentaires, je ne vais pas le lire :)

Pour les trackbacks, si vous leur consacrez 1 Mo, vous pourriez facilement avoir plus de 10k (probablement plus près de 20k)

Donc, à l'exception des situations vraiment bizarres, cela fonctionnera très bien. Et dans le cas d'exception ou de spam, je ne pense vraiment pas que vous voudriez un objet de 20 Mo de toute façon. Je pense que plafonner les trackbacks à environ 15k a beaucoup de sens, peu importe les performances. Ou du moins un boîtier spécial si cela arrive.

-Éliot

Je pense que vous auriez du mal à atteindre la limite ... et avec le temps, si vous mettez à niveau ... vous devrez vous inquiéter de moins en moins.

Le point principal de la limite est de ne pas utiliser toute la RAM de votre serveur (car vous devez charger tous MBles documents dans la RAM lorsque vous l'interrogez.)

La limite est donc de quelques% de RAM utilisable normale sur un système commun ... qui continuera de croître d'année en année.

Remarque sur le stockage de fichiers dans MongoDB

Si vous avez besoin de stocker des documents (ou des fichiers) plus volumineux que 16MBvous pouvez utiliser l' API GridFS qui divisera automatiquement les données en segments et vous les restituera (évitant ainsi le problème des limites de taille / RAM.)

Au lieu de stocker un fichier dans un seul document, GridFS divise le fichier en parties, ou blocs, et stocke chaque bloc dans un document distinct.

GridFS utilise deux collections pour stocker les fichiers. Une collection stocke les morceaux de fichier et l'autre les métadonnées de fichier.

Vous pouvez utiliser cette méthode pour stocker des images, des fichiers, des vidéos, etc. dans la base de données comme vous le feriez dans une base de données SQL. Je l'ai utilisé pour même stocker des fichiers vidéo de plusieurs gigaoctets.

Justin Jenkins
la source
2
C'est génial que vous ayez assez de RAM pour toute votre base de données ... Typiquement, le "jeu de travail" est en RAM, pas toute la base de données (comme dans mon cas, j'ai plus d'une base de données de x Go où si tout additionné dépasserait ma RAM, mais ce n'est pas grave car l'ensemble de travail est beaucoup, beaucoup plus petit.) De plus, s'il n'y avait pas de limite, vous pourriez charger un document de 800 Mo dans la RAM avec une requête et un document de 400 k avec un autre, ce qui rend l'équilibrage de votre RAM un peu difficile, etc. . Ainsi, la «limite» est de quelques% de la RAM du serveur typique (donc elle augmente avec le temps.) Mongodb.org/display/DOCS/Checking+Server+Memory+Usage
Justin Jenkins
3
C'est génial que vous puissiez tout stocker dans la RAM, mais pensez à l'efficacité et à l'idiome des articles de blog. Vous voulez évidemment qu'un message soit en mémoire s'il est lu. Mais voulez-vous vraiment que 10 pages de commentaires pour un article de blog soient en mémoire alors que la plupart des gens ne liront jamais au-delà de la première page? Bien sûr, vous pouvez le faire et si votre base de données est suffisamment petite pour qu'elle puisse tout tenir en mémoire, pas de problème. Mais en termes d'efficacité pure, vous ne voulez pas que les bits inutiles occupent de l'espace mémoire si vous pouvez l'éviter (et cela vaut également pour le SGBDR).
AlexGad
50
doux Jésus, donc l'argument de Mongo est "16 Mo devraient suffire à n'importe qui"? Ce n'est pas comme ça qui s'est avéré incorrect dans le passé.
Robert Christ
2
Cela me semble dommage. Mongo est censé être utile pour le Big Data, pas de telles limitations. Dans mon projet, j'ai besoin d'agréger et de regrouper les tweets qui sont liés au même sujet de tendance, et cela pourrait se retrouver dans plus de 20000 tweets pour une période de 20 heures (et il est fort possible qu'il y ait des tendances d'une durée supérieure à 20 heures dans ma db). Avoir autant de tweets et stocker leur texte en même temps est dévastateur et après avoir regroupé quelques petites tendances, cela finit exceptionnellement sur une grande tendance.
Savvas Parastatidis
7
@savvas pourquoi mettriez-vous tous les tweets dans un seul document? Utilisez un document par tweet, placez le sujet tendance comme un autre champ sur le document. mettez un index sur ce champ de sujet, puis agrégez-le sur ce champ à l'aide du pipeline mongo. il faut ajuster la façon dont vous faites les choses pour travailler avec nosql, une fois que vous ajustez vos méthodes et que vous pensez que cela fonctionne très bien pour de nombreux cas d'utilisation de Big Data.
schmidlop le
32

De nombreux membres de la communauté préféreraient qu'il n'y ait pas de limite avec des avertissements sur les performances, voir ce commentaire pour un argument bien raisonné: https://jira.mongodb.org/browse/SERVER-431?focusedCommentId=22283&page=com.atlassian.jira.plugin. system.issuetabpanels: comment-tabpanel # comment-22283

À mon avis, les développeurs principaux sont têtus sur ce problème car ils ont décidé très tôt que c'était une «fonctionnalité» importante. Ils ne vont pas le changer de sitôt parce que leurs sentiments sont blessés que quiconque la remette en question. Un autre exemple de personnalité et de politique nuisant à un produit dans les communautés open source, mais ce n'est pas vraiment un problème paralysant.

marr75
la source
5
Je suis tout à fait d'accord avec vous, cela va également à l'encontre de l'objectif d'avoir des documents intégrés maintenant, car la plupart des documents intégrés franchiront désormais facilement la limite. Esp avec un éventail de documents à l'intérieur
Sharjeel Ahmed
@ marr75 il dit corrigé maintenant, a-t-il été corrigé?
Mafii
1
Je veux dire, la limite a été augmentée à 16 Mo, cela ne résout pas le «problème» à long terme; OMI, la limite devrait simplement être éliminée.
marr75
2
Fil de 6 ans nécro. Je ne suis absolument pas convaincu par votre mauvais cas d'utilisation / exemple de conception. En outre, cet exemple est bien meilleur pour illustrer pourquoi vous devez valider les entrées que d'avoir une limite de taille de document unique dans la base de données. Faire en sorte que l'application divise ses documents imbriqués en documents individuels dans une autre collection ou commence un nouveau document de «continuation» (solutions que j'ai utilisées plusieurs fois pour travailler dans cette limite) avait peu d'impact sur les performances mais de gros impacts sur la complexité du code. Le point entier des DB de document est la localité des données.
marr75
4
Merci d'avoir fait le même calcul que les documents mongoDB pour défendre cette décision, mais votre cas d'utilisation unique et votre expérience de réflexion sont loin d'être concluants. J'ai dû proposer des conceptions complexes et redondantes pour contourner le fait qu'il existe une limite arbitraire qui est atteinte par mongo (sans entrées profondément imbriquées ou dupliquées, btw). Selon votre logique, aucune base de données ne devrait avoir besoin de contenir plus de 16 Mo au total, car un texte arbitraire peut être représenté en utilisant moins de stockage. C'est évidemment idiot.
marr75
31

Pour publier une réponse de clarification ici pour ceux qui sont dirigés ici par Google.

La taille du document comprend tout ce qui se trouve dans le document, y compris les sous-documents, les objets imbriqués, etc.

Donc un document de:

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

A une taille maximale de 16meg.

Les sbudocuments et les objets imbriqués sont tous comptés dans la taille du document.

Sammaye
la source
La structure la plus grande possible pouvant être représentée dans BSON est, ironiquement, aussi la plus compacte. Malgré le fait que MongoDB utilise des size_tindex de tableau (64 bits) en interne, la limite de taille de document de 16 Mo serait, au mieux, capable de représenter un document contenant un seul tableau contenant lui-même deux millions de NULL.
amcgregor
Toutes mes excuses, ajout d'un deuxième commentaire pour adresser / clarifier un autre détail important: lorsque vous dites que la taille du document comprend tout ce qui se trouve dans le document , cela inclut également les clés . Par exemple, {"f": 1}est de deux octets plus petit que {"foo": 1}. Cela peut rapidement s'additionner si vous ne faites pas attention, bien que la compression moderne sur disque aide.
amcgregor
6

Je n'ai pas encore vu de problème avec la limite qui n'impliquait pas de gros fichiers stockés dans le document lui-même. Il existe déjà une variété de bases de données qui sont très efficaces pour stocker / récupérer des fichiers volumineux; ils sont appelés systèmes d'exploitation. La base de données existe en tant que couche sur le système d'exploitation. Si vous utilisez une solution NoSQL pour des raisons de performances, pourquoi voudriez-vous ajouter une surcharge de traitement supplémentaire à l'accès de vos données en plaçant la couche DB entre votre application et vos données?

JSON est un format de texte. Donc, si vous accédez à vos données via JSON, cela est particulièrement vrai si vous avez des fichiers binaires car ils doivent être encodés en uuencode, hexadécimal ou Base 64. Le chemin de conversion peut ressembler à

fichier binaire <> JSON (encodé) <> BSON (encodé)

Il serait plus efficace de mettre le chemin (URL) du fichier de données dans votre document et de conserver les données elles-mêmes en binaire.

Si vous voulez vraiment conserver ces fichiers de longueur inconnue dans votre base de données, vous feriez probablement mieux de les mettre dans GridFS et de ne pas risquer de tuer votre concurrence lors de l'accès aux fichiers volumineux.

Chris Golledge
la source
1
"Il existe déjà une variété de bases de données qui sont très efficaces pour stocker / récupérer des fichiers volumineux; on les appelle des systèmes d'exploitation."; Voir blog.mongodb.org/post/183689081/…
redcalx
6

Profondeur imbriquée pour les documents BSON: MongoDB ne prend pas en charge plus de 100 niveaux d'imbrication pour les documents BSON.

Plus plus d'infos voir

user2903536
la source
2

Peut-être que stocker une relation article de blog -> commentaires dans une base de données non relationnelle n'est pas vraiment la meilleure conception.

Vous devriez probablement stocker les commentaires dans une collection séparée des articles de blog de toute façon.

[Éditer]

Voir les commentaires ci-dessous pour une discussion plus approfondie.

Mchl
la source
15
Je ne suis pas du tout d'accord. Les commentaires dans les documents de votre blog devraient être parfaitement bien dans MongoDB ... c'est une utilisation très courante (je l'utilise à plusieurs endroits en production et cela fonctionne assez bien.)
Justin Jenkins
2
J'ai peut-être été trop strict dans ma réponse. Il n'y a rien de mal à stocker les articles de blog et les commentaires associés dans MongoDB ou dans une base de données similaire. C'est plus que les gens ont tendance à abuser des capacités des bases de données basées sur des documents (l'exemple le plus radical serait de stocker toutes vos données dans un seul document appelé `` blog '')
Mchl
3
@Mchel: "blog" n'est pas bon, mais stocker les commentaires dans une collection séparée est tout aussi mauvais pour les mêmes raisons. Les messages avec un tableau de commentaires sont comme, l'exemple canonique d'un document db.
Matt Briggs
6
@SoPeople: stocker des commentaires dans un article est comme l'exemple canonique des bases de données orientées document. (comme stocker l'intégralité d'un texte wiki dans un seul document) Si je devais écrire SO, il fonctionnerait complètement sur MongoDB. Aucune de ces entrées SO ne dépassera raisonnablement 4 Mo. Craigslist effectue une migration de base de données géante de son histoire vers MongoDB. Ils n'avaient que quelques documents dépassant cette limite et le développeur principal a suggéré que les documents eux-mêmes avaient été effectivement détruits (à la suite de quelques bogues). Encore une fois, 4 Mo, c'est plusieurs romans de texte.
Gates VP
3
@Gates VP, je suis d'accord sur l'utilisation d'un moteur de texte intégral distinct. Je pensais à une recherche de métadonnées. Que faire si vous avez un ensemble de documents Livres et que vous souhaitez trouver tous les livres publiés en 1982? Si chaque livre contient + 100 Ko de texte, vous ne voulez pas transférer plusieurs mégaoctets juste pour afficher les 20 premiers titres de livres.
mikerobi
0

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

Si vous pensez qu'un article de blog peut dépasser la limite de 16 Mo de document, vous devez extraire les commentaires dans une collection distincte et référencer l'article de blog à partir du commentaire et effectuer une jointure au niveau de l'application.

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

// comments
[
  {
    text: 'a comment'
    post: ObjectID('AAAA')
  },
  {
    text: 'another comment'
    post: ObjectID('AAAA')
  }
]
mzarrugh
la source