Comprensión del límite de tamaño de documento BSON de MongoDB

153

De MongoDB La guía definitiva:

Los documentos de más de 4 MB (cuando se convierten a BSON) no se pueden guardar en la base de datos. Este es un límite algo arbitrario (y puede aumentarse en el futuro); es principalmente para evitar un mal diseño de esquema y garantizar un rendimiento constante.

No entiendo este límite, ¿significa esto que un documento que contiene una publicación de blog con muchos comentarios y que es mayor que 4 MB no se puede almacenar como un solo documento?

¿Esto también cuenta los documentos anidados?

¿Qué pasaría si quisiera un documento que audite los cambios a un valor? (Eventualmente puede crecer, excediendo el límite de 4MB).

Espero que alguien explique esto correctamente.

Acabo de empezar a leer sobre MongoDB (primera base de datos nosql sobre la que estoy aprendiendo).

Gracias.

Santo
fuente
55
Creo que la pregunta debería aclarar que esto es una limitación de los tamaños de documentos almacenados de MongoDB y no del formato BSON.
alexpopescu
2
Sin embargo, acabo de intentar guardar un documento enorme que ciertamente supera los 4 MB para obtener el mensaje "BSON :: InvalidDocument: Documento demasiado grande: los documentos BSON están limitados a 4194304 bytes". Si ese es el caso, ¿no es un poco engañoso en el mensaje de advertencia / error?
Nik So
18
Puede encontrar fácilmente el tamaño máximo de su documento BSON con el db.isMaster().maxBsonObjectSize/(1024*1024)+' MB'comando en el mongoshell.
AhmetB - Google
55
¿Cuál es el propósito de nosql sin esquema, donde no puede volcar registros de más de 16 mb y construir una operación de crud encima de él!
Rizwan Patel
Creo que la cita inicial lo dice todo ... El límite está en su lugar para evitar un mal diseño de esquema. Si, por ejemplo, tiene una publicación con muchos comentarios, desearía una colección de entradas de blog y una colección de comentarios, o una colección de cambios. El diseño de mongo / nosql permite cosas de gran tamaño como redes de documentos, pero el desarrollador necesita dividirlas en partes que tengan sentido. Si no se establece un límite de tamaño, ocurrirán otros problemas. Creo que el límite de 4 MB estaba bien. 16mb, genial! Pero si estoy escribiendo un documento de 16 MB, eso es una pista de que algo más está mal con el diseño.
Pestaña

Respuestas:

126

En primer lugar, esto se plantea en la próxima versión para 8MBo 16MB... pero creo que para poner esto en perspectiva, Eliot de 10gen (que desarrolló MongoDB) lo expresa mejor:

EDITAR: El tamaño ha sido oficialmente 'elevado' a16MB

Entonces, en el ejemplo de su blog, 4 MB es en realidad mucho. Por ejemplo, el texto completo sin comprimir de "La guerra de los mundos" es solo 364k (html): http://www.gutenberg.org/etext/36

Si tu publicación de blog es tan larga con tantos comentarios, por mi parte no la voy a leer :)

Para los trackbacks, si les dedicó 1 MB, fácilmente podría tener más de 10k (probablemente más cerca de 20k)

Entonces, excepto en situaciones realmente extrañas, funcionará muy bien. Y en el caso de excepción o spam, realmente no creo que quieras un objeto de 20mb de todos modos. Creo que limitar los trackbacks como 15k más o menos tiene mucho sentido, sin importar el rendimiento. O al menos una carcasa especial si alguna vez sucede.

-Eliot

Creo que sería muy difícil llegar al límite ... y con el tiempo, si actualizas ... tendrás que preocuparte cada vez menos.

El punto principal del límite es que no use toda la RAM en su servidor (ya que necesita cargar todos MBlos documentos en la RAM cuando lo consulta).

Entonces, el límite es un% de la RAM utilizable normal en un sistema común ... que seguirá creciendo año tras año.

Nota sobre el almacenamiento de archivos en MongoDB

Si necesita almacenar documentos (o archivos) más grandes de lo 16MBque puede, use la API de GridFS que dividirá automáticamente los datos en segmentos y los transmitirá de nuevo a usted (evitando así el problema con los límites de tamaño / RAM).

En lugar de almacenar un archivo en un solo documento, GridFS divide el archivo en partes o fragmentos, y almacena cada fragmento como un documento separado.

GridFS usa dos colecciones para almacenar archivos. Una colección almacena los fragmentos de archivo y la otra almacena los metadatos del archivo.

Puede usar este método para almacenar imágenes, archivos, videos, etc. en la base de datos de la misma manera que lo haría en una base de datos SQL. Lo he usado incluso para almacenar archivos de video de varios gigabytes.

Justin Jenkins
fuente
2
Es increíble que tengas suficiente RAM para toda tu base de datos ... Por lo general, el "conjunto de trabajo" está en RAM, no en toda la base de datos (como en mi caso tengo más de una base de datos de x GBs donde si todo sumado excedería mi RAM, pero está bien porque el conjunto de trabajo es mucho, mucho más pequeño). Además, si no hubiera límite, podría cargar un documento de 800 MB en RAM con una consulta y un documento de 400 k con otro, lo que dificulta un poco el equilibrio de su RAM, etc. Entonces, el "límite" es un porcentaje de la RAM típica del servidor (por lo tanto, crece con el tiempo). Mongodb.org/display/DOCS/Checking+Server+Memory+Usage
Justin Jenkins
3
Es genial que pueda almacenar todo en RAM, pero tenga en cuenta la eficiencia y el idioma de publicación de blog. Obviamente desea que una publicación esté en la memoria si se lee. Pero, ¿realmente quieres 10 páginas de comentarios para una publicación de blog en la memoria cuando la mayoría de la gente nunca leerá más allá de la primera página? Claro, puede hacerlo y si su base de datos es lo suficientemente pequeña como para que quepa en la memoria, entonces no hay problema. Pero en términos de eficiencia pura, no desea que los bits inútiles ocupen espacio en la memoria si puede evitarlo (y eso también se aplica a RDBMS).
AlexGad
50
dulce Jesús, ¿entonces el argumento de Mongo es "16 MB deberían ser suficientes para cualquiera"? No es que eso haya demostrado ser incorrecto en el pasado.
Robert Christ
2
Esto me parece muy malo. Se supone que Mongo es útil para Big Data, no tiene tales limitaciones. En mi proyecto, necesito agregar y agrupar tweets relacionados con el mismo tema de tendencia, y esto podría terminar en más de 20000 tweets por un período de tiempo de 20 horas (y es muy posible que haya tendencias que duren más de 20 horas en mi db). Tener tantos tweets y almacenar su texto al mismo tiempo es devastador y después de agrupar algunas pequeñas tendencias, termina con la excepción de una gran tendencia.
Savvas Parastatidis
77
@savvas, ¿por qué pondrías todos los tweets en un solo documento? Use un documento por tweet, coloque el tema de tendencia como otro campo en el documento. ponga un índice en ese campo de tema y luego agregue en ese campo usando la canalización de mongo. toma un poco de ajuste de cómo hacer las cosas para trabajar con nosql, una vez que ajuste sus métodos y piense que encontrará que funciona muy bien para muchos casos de uso de big data.
schmidlop
32

Muchos en la comunidad preferirían no tener límite con las advertencias sobre el rendimiento, vea este comentario para ver un argumento bien razonado: https://jira.mongodb.org/browse/SERVER-431?focusedCommentId=22283&page=com.atlassian.jira.plugin. system.issuetabpanels: comment-tabpanel # comment-22283

Mi opinión, los desarrolladores principales son tercos sobre este problema porque decidieron que era una "característica" importante desde el principio. No lo van a cambiar en el corto plazo porque sus sentimientos están heridos porque alguien lo cuestionó. Otro ejemplo de personalidad y política que perjudica a un producto en las comunidades de código abierto, pero este no es realmente un problema paralizante.

marr75
fuente
55
Estoy totalmente de acuerdo con usted, también anula el propósito de tener documentos incrustados ahora, ya que la mayoría de los documentos incrustados ahora cruzarán el límite fácilmente. Esp con una variedad de documentos dentro de ellos
Sharjeel Ahmed
@ marr75 dice arreglado ahora, ¿ha sido arreglado?
Mafii
1
Quiero decir, el límite se elevó a 16 MB, eso no soluciona el "problema" a largo plazo; OMI, el límite debería ser eliminado.
marr75
2
Hilo de 6 años necro. No estoy convencido por su ejemplo de diseño / caso de mal uso específico. Además, ese ejemplo es mucho mejor para ilustrar por qué necesita validar entradas que tener un límite de tamaño de documento único de base de datos. Hacer que la aplicación dividiera sus documentos anidados como documentos individuales en otra colección o comenzar un nuevo documento de "continuación" (las soluciones que he usado varias veces para trabajar dentro de este límite) tuvieron poco impacto en el rendimiento pero grandes impactos en la complejidad del código. El punto completo de las bases de datos de documentos es la localidad de datos.
marr75
44
Gracias por hacer las mismas matemáticas que hacen los documentos de mongoDB para defender esta decisión, pero su caso de uso único y su experimento de pensamiento dista mucho de ser concluyente. He tenido que idear diseños complejos y redundantes para solucionar el hecho de que existe un límite arbitrario que es golpeado por mongo (sin entradas profundamente anidadas o duplicadas, por cierto). Según su lógica, ninguna base de datos debería necesitar contener más de 16 MB en total porque se puede representar un texto arbitrario utilizando menos almacenamiento. Esto es obviamente tonto.
marr75
31

Para publicar una aclaración, responda aquí para aquellos a quienes Google dirige aquí.

El tamaño del documento incluye todo en el documento, incluidos los subdocumentos, los objetos anidados, etc.

Entonces un documento de:

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

Tiene un tamaño máximo de 16meg.

Sbudocuments y objetos anidados se cuentan para el tamaño del documento.

Sammaye
fuente
La estructura más grande posible que se puede representar en BSON es, irónicamente, también la más compacta. A pesar del hecho de que MongoDB usa size_tíndices de matriz (64 bits) internamente, el límite de tamaño de documento de 16 MB sería, en el mejor de los casos, capaz de representar un documento que contenga una sola matriz que contenga dos millones de NULL.
amcgregor
Disculpas, agregar un segundo comentario para abordar / aclarar otro detalle importante: cuando dice que el tamaño del documento incluye todo en el documento , eso también incluye las claves . Por ejemplo, {"f": 1}es dos bytes más pequeño que {"foo": 1}. Esto puede sumar rápidamente si no tiene cuidado, aunque la compresión moderna en disco ayuda.
amcgregor
6

Todavía no he visto un problema con el límite que no involucre archivos grandes almacenados dentro del documento mismo. Ya hay una variedad de bases de datos que son muy eficientes para almacenar / recuperar archivos grandes; Se llaman sistemas operativos. La base de datos existe como una capa sobre el sistema operativo. Si está utilizando una solución NoSQL por razones de rendimiento, ¿por qué desearía agregar una sobrecarga de procesamiento adicional al acceso de sus datos colocando la capa de base de datos entre su aplicación y sus datos?

JSON es un formato de texto. Entonces, si está accediendo a sus datos a través de JSON, esto es especialmente cierto si tiene archivos binarios porque tienen que estar codificados en uuencode, hexadecimal o Base 64. La ruta de conversión podría verse así

archivo binario <> JSON (codificado) <> BSON (codificado)

Sería más eficiente poner la ruta (URL) al archivo de datos en su documento y mantener los datos en binario.

Si realmente desea mantener estos archivos de longitud desconocida en su base de datos, probablemente sea mejor ponerlos en GridFS y no arriesgarse a matar su concurrencia cuando se accede a los archivos grandes.

Chris Golledge
fuente
1
"Ya hay una variedad de bases de datos que son muy eficientes para almacenar / recuperar archivos grandes; se denominan sistemas operativos"; Ver blog.mongodb.org/post/183689081/…
redcalx
6

Profundidad anidada para documentos BSON: MongoDB admite no más de 100 niveles de anidamiento para documentos BSON.

Más más información vist

usuario2903536
fuente
2

Quizás almacenar una publicación de blog -> relación de comentarios en una base de datos no relacional no es realmente el mejor diseño.

De todos modos, probablemente debería almacenar los comentarios en una colección separada para las publicaciones de blog.

[editar]

Vea los comentarios a continuación para mayor discusión.

Mchl
fuente
15
No estoy de acuerdo en absoluto. Los comentarios en los documentos de su blog deberían estar perfectamente bien en MongoDB ... es un uso muy común (lo uso en más de un lugar en producción y funciona bastante bien)
Justin Jenkins
2
Quizás fui demasiado estricto en mi respuesta. No hay nada de malo en almacenar publicaciones de blog y comentarios asociados en MongoDB o una base de datos similar. Es más que las personas tienden a usar en exceso las capacidades que dan las bases de datos basadas en documentos (el ejemplo más radical sería almacenar todos sus datos en un solo documento llamado 'blog')
Mchl
3
@Mchel: "blog" no es bueno, pero almacenar comentarios en una colección separada es igual de malo por las mismas razones. Las publicaciones con una matriz de comentarios son como, el ejemplo canónico de un documento db.
Matt Briggs el
66
@SoPeople: almacenar comentarios dentro de una publicación es como el ejemplo canónico de bases de datos orientadas a documentos. (como almacenar la totalidad de un texto wiki dentro de un documento) Si escribiera SO, se ejecutaría completamente en MongoDB. Ninguna de estas entradas SO excederá razonablemente los 4 MB. Craigslist está haciendo una migración de DB gigante de su historia a MongoDB. Solo tenían un par de documentos que superaban ese límite y el desarrollador principal sugirió que los documentos en sí mismos fueron reventados (el resultado de algunos errores). Nuevamente, 4 megas son varias novelas de texto.
Gates VP
3
Vicepresidente de @Gates, estoy de acuerdo en usar un motor de texto completo por separado. Estaba pensando en una búsqueda de metadatos. ¿Qué sucede si tiene un conjunto de documentos de libros y desea encontrar todos los libros publicados en 1982? Si cada libro tiene + 100kb de texto, no desea transferir varios megabytes solo para mostrar los primeros 20 títulos de libros.
mikerobi
0

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

Si espera que una publicación de blog supere el límite de documentos de 16Mb, debe extraer los comentarios en una colección separada y hacer referencia a la publicación de blog desde el comentario y hacer una unión a nivel de aplicación.

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

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