Entendendo o limite de tamanho do documento MongoDB BSON


153

Do MongoDB O Guia Definitivo:

Documentos maiores que 4 MB (quando convertidos em BSON) não podem ser salvos no banco de dados. Esse é um limite um tanto arbitrário (e pode ser aumentado no futuro); é principalmente para evitar o mau design do esquema e garantir um desempenho consistente.

Eu não entendo esse limite. Isso significa que um documento contendo uma postagem de blog com muitos comentários que, por coincidência, é maior que 4 MB, não pode ser armazenado como um único documento?

Também isso conta os documentos aninhados também?

E se eu quisesse um documento que audita as alterações em um valor. (Eventualmente, poderá crescer, excedendo o limite de 4 MB.)

Espero que alguém explique isso corretamente.

Comecei a ler sobre o MongoDB (primeiro banco de dados nosql que estou aprendendo).

Obrigado.


5
Acho que a pergunta deve esclarecer que essa é uma limitação dos tamanhos de documentos armazenados do MongoDB e não do formato BSON.
Alexpopescu

2
No entanto, tentei salvar um documento enorme que certamente excede 4 MB para obter a mensagem "BSON :: InvalidDocument: Documento muito grande: documentos BSON são limitados a 4194304 bytes". Se for esse o caso, não é enganoso na mensagem de aviso / erro?
Nik So

18
Você pode encontrar facilmente o tamanho máximo do seu documento BSON com o db.isMaster().maxBsonObjectSize/(1024*1024)+' MB'comando no mongoshell.
AhmetB - Google

5
qual é o objetivo do nosql sem esquema em que você não pode despejar registros com mais de 16 mb e criar uma operação crud sobre ela!
Rizwan Patel

Acho que a citação inicial já diz tudo ... O limite está em vigor para evitar o mau design do esquema. Se, por exemplo, você tem uma postagem com muitos comentários, deseja uma coleção de entradas de blog e uma coleção de comentários ou uma coleção de alterações. O design do mongo / nosql permite coisas de tamanho maciço como redes de documentos, mas o desenvolvedor precisa dividi-las em partes que façam sentido. Se nenhum limite de tamanho for definido, outros problemas ocorrerão. Eu acho que o limite de 4mb estava bom. 16mb, ótimo! Mas se estou escrevendo um documento de 16 MB, é uma pista de que algo mais está errado com o design.
Cílios

Respostas:


126

Primeiro, isso realmente está sendo levantado na próxima versão para 8MBou 16MB... mas acho que para colocar isso em perspectiva, Eliot da 10gen (que desenvolveu o MongoDB) coloca da melhor maneira:

EDIT: O tamanho foi oficialmente 'aumentado' para16MB

Portanto, no exemplo do seu blog, 4 MB são na verdade muitos. Por exemplo, o texto descompactado completo de "Guerra dos Mundos" tem apenas 364k (html): http://www.gutenberg.org/etext/36

Se o seu blog é muito longo com tantos comentários, eu não o leio :)

Para trackbacks, se você dedicar 1 MB a eles, poderá facilmente ter mais de 10k (provavelmente mais perto de 20k)

Portanto, exceto em situações verdadeiramente bizarras, funcionará muito bem. E no caso de exceção ou spam, realmente não acho que você desejaria um objeto de 20 MB. Acho que limitar os trackbacks com mais ou menos 15k faz muito sentido, independentemente do desempenho. Ou pelo menos invólucro especial, se isso acontecer.

-Eliot

Acho que seria muito difícil atingir o limite ... e, com o tempo, se você atualizar ... precisará se preocupar cada vez menos.

O ponto principal do limite é que você não gaste toda a RAM do seu servidor (pois você precisará carregar todos os MBs do documento na RAM ao consultá-lo.)

Portanto, o limite é de alguns% da RAM utilizável normal em um sistema comum ... que continuará crescendo ano a ano.

Nota sobre o armazenamento de arquivos no MongoDB

Se você precisar armazenar documentos (ou arquivos) maiores do que 16MBvocê pode usar a API do GridFS, que dividirá automaticamente os dados em segmentos e os transmitirá de volta para você (evitando assim o problema com limites de tamanho / RAM).

Em vez de armazenar um arquivo em um único documento, o GridFS divide o arquivo em partes ou partes e armazena cada parte como um documento separado.

O GridFS usa duas coleções para armazenar arquivos. Uma coleção armazena os blocos de arquivos e a outra armazena metadados de arquivos.

Você pode usar esse método para armazenar imagens, arquivos, vídeos etc. no banco de dados, da mesma forma que você pode em um banco de dados SQL. Eu usei isso para armazenar até arquivos de vídeo com vários gigabytes.


2
É incrível que você tenha RAM suficiente para todo o banco de dados ... Normalmente, o "conjunto de trabalho" está na RAM, e não no banco de dados inteiro (como no meu caso, eu tenho mais de um banco de dados de x GBs em que se todos somados excederem minha RAM, mas tudo bem, porque o conjunto de trabalho é muito, muito menor.) Além disso, se não houvesse limite, você poderia carregar um documento de 800 MB na RAM com uma consulta e um documento de 400k com outra, dificultando o equilíbrio da RAM e etc. . assim, o "limite" é algum% de RAM servidor típico (assim ela cresce ao longo do tempo.) mongodb.org/display/DOCS/Checking+Server+Memory+Usage
Justin Jenkins

3
É ótimo que você possa armazenar tudo na RAM, mas considere a eficiência e o idioma da postagem do blog. Obviamente, você quer que um post fique na memória se for lido. Mas você realmente deseja que 10 páginas de comentários de uma postagem do blog estejam na memória quando a maioria das pessoas nunca lerá a primeira página? Claro, você pode fazer isso e se o seu banco de dados for pequeno o suficiente para caber na memória, não há problema. Mas em termos de eficiência pura, você não deseja que bits inúteis ocupem espaço na memória, se puder evitá-lo (e isso vale também para RDBMS).
AlexGad

50
doce Jesus, então o argumento de Mongo é "16 MB deve ser suficiente para alguém"? Não é assim que alguma vez provou estar incorreto no passado.
Robert Christ

2
Isso parece muito ruim para mim. O Mongo deve ser útil para big data, sem essas limitações. No meu projeto, preciso agregar e agrupar tweets relacionados ao mesmo tópico de tendência, e isso pode acabar em mais de 20.000 tweets por um período de 20 horas (e é bem possível que existam tendências que durem mais de 20 horas no meu db). Ter tantos tweets e armazenar seu texto ao mesmo tempo é devastador e, depois de agrupar algumas pequenas tendências, termina com exceção de uma grande tendência.
Savvas Parastatidis

7
@savvas Por que você colocaria todos os tweets em um único documento? Use um documento por tweet, coloque o tópico de tendências como outro campo no documento. coloque um índice nesse campo de tópico e agregue-o usando o pipeline mongo. é necessário algum ajuste na maneira como você faz as coisas para trabalhar com o nosql, depois de ajustar seus métodos e pensar que você achará que funciona muito bem para muitos casos de uso de big data.
schmidlop

32

Muitos na comunidade preferem não ter limites com avisos sobre desempenho, veja este comentário por um argumento bem fundamentado: https://jira.mongodb.org/browse/SERVER-431?focusedCommentId=22283&page=com.atlassian.jira.plugin. system.issuetabpanels: comment-tabpanel # comment-22283

Na minha opinião, os desenvolvedores principais são teimosos sobre esse problema porque decidiram que esse era um "recurso" importante desde o início. Eles não vão mudar isso tão cedo, porque seus sentimentos estão magoados por alguém ter questionado. Outro exemplo de personalidade e política que prejudica um produto em comunidades de código aberto, mas esse não é realmente um problema prejudicial.


5
Eu concordo totalmente com você, também anula o propósito de ter documentos incorporados agora, já que a maioria dos documentos incorporados agora ultrapassará facilmente o limite. Esp com vários documentos dentro deles
Sharjeel Ahmed 15/02

@ marr75 diz fixo agora, foi corrigido?
precisa saber é

1
Quero dizer, o limite foi aumentado para 16 MB, o que não corrige o "problema" a longo prazo; OMI, o limite deve ser eliminado.
755 marr75

2
Necro de 6 anos de idade. Não estou convencido de seu exemplo específico de caso de uso / projeto ruim. Além disso, esse exemplo é muito melhor para ilustrar por que você precisa validar entradas do que ter um limite de tamanho de documento único para o banco de dados. Fazer o aplicativo dividir seus documentos aninhados como documentos individuais em outra coleção ou iniciar um novo documento de "continuação" (soluções que usei várias vezes para trabalhar dentro desse limite) teve pouco impacto no desempenho, mas grandes na complexidade do código. O ponto inteiro dos bancos de dados do documento é a localidade dos dados.
marr75 24/05

4
Obrigado por fazer a mesma matemática que os documentos do mongoDB fazem para defender essa decisão, mas seu único caso de uso e experiência de pensamento está longe de ser conclusivo. Eu tive que criar designs redundantes e complexos para solucionar o fato de que há um limite arbitrário que é atingido pelo mongo (sem entradas profundamente aninhadas ou duplicadas, btw). Pela sua lógica, nenhum banco de dados precisa conter mais de 16 MB no total, porque algum texto arbitrário pode ser representado usando menos armazenamento. Isso é obviamente bobo.
marr75

31

Para postar uma resposta de esclarecimento aqui para quem é direcionado aqui pelo Google.

O tamanho do documento inclui tudo no documento, incluindo subdocumentos, objetos aninhados etc.

Então, um 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},{}]}
    ]
}

Tem um tamanho máximo de 16meg.

Sbudocuments e objetos aninhados são contados para o tamanho do documento.


A maior estrutura possível que pode ser representada no BSON é, ironicamente, também a mais compacta. Apesar do MongoDB usar size_tinternamente índices de matriz (64 bits), o limite de tamanho de documento de 16 MB poderia, na melhor das hipóteses, representar um documento contendo uma única matriz contendo dois milhões de NULLs.
amcgregor

Desculpas, adicionando um segundo comentário para abordar / esclarecer outro detalhe importante: quando você diz que o tamanho do documento inclui tudo no documento , isso também inclui as chaves . Por exemplo, {"f": 1}é dois bytes menor que {"foo": 1}. Isso pode aumentar rapidamente se você não for cuidadoso, embora a compactação moderna no disco ajude.
amcgregor

6

Ainda não vi um problema com o limite que não envolvia arquivos grandes armazenados no próprio documento. Já existe uma variedade de bancos de dados que são muito eficientes para armazenar / recuperar arquivos grandes; eles são chamados de sistemas operacionais. O banco de dados existe como uma camada sobre o sistema operacional. Se você estiver usando uma solução NoSQL por motivos de desempenho, por que você deseja adicionar sobrecarga de processamento adicional ao acesso aos seus dados colocando a camada de banco de dados entre o aplicativo e os dados?

JSON é um formato de texto. Portanto, se você estiver acessando seus dados por meio do JSON, isso é especialmente verdadeiro se você tiver arquivos binários, pois eles precisam ser codificados em uuencode, hexadecimal ou Base 64. O caminho da conversão pode parecer

arquivo binário <> JSON (codificado) <> BSON (codificado)

Seria mais eficiente colocar o caminho (URL) para o arquivo de dados no seu documento e manter os dados em binário.

Se você realmente deseja manter esses arquivos de tamanho desconhecido no seu banco de dados, provavelmente seria melhor colocá-los no GridFS e não correr o risco de matar sua simultaneidade quando os arquivos grandes forem acessados.


1
"Já existe uma variedade de bancos de dados que são muito eficientes no armazenamento / recuperação de arquivos grandes; eles são chamados de sistemas operacionais."; Veja blog.mongodb.org/post/183689081/…
redcalx


2

Talvez armazenar um post -> comentários relação em um banco de dados não-relacional não é realmente o melhor design.

Provavelmente, você deve armazenar os comentários em uma coleção separada nas postagens do blog.

[editar]

Veja os comentários abaixo para uma discussão mais aprofundada.


15
Eu não concordo nada. Comentários em seu blog documentos post devem estar perfeitamente bem no MongoDB ... é um uso muito comum (eu usá-lo mais do que um lugar na produção e ele funciona muito bem.)
Justin Jenkins

2
Talvez eu tenha sido excessivamente rigoroso em minha resposta. Não há nada de errado em armazenar postagens de blog e comentários associados no MongoDB ou banco de dados semelhante. É mais que as pessoas tendem a usar demais as habilidades documentar bancos de dados baseados dar (exemplo mais radical seria para armazenar todos os seus dados em um único documento chamado 'blog')
Mchl

3
@Mchel: "blog" não é bom, mas armazenar comentários em uma coleção separada é tão ruim pelos mesmos motivos. Postagens com uma matriz de comentários é como, o exemplo canônico de um documento db.
Matt Briggs

6
@SoPeople: armazenar comentários em uma postagem é como o exemplo canônico de bancos de dados orientados a documentos. (como armazenar a totalidade de um texto wiki dentro de um documento) Se eu escrevesse o SO, ele seria executado completamente no MongoDB. Nenhuma dessas entradas de SO excederá razoavelmente 4 MB. O Craigslist está fazendo uma gigantesca migração de banco de dados de sua história para o MongoDB. Eles tiveram apenas alguns documentos ultrapassando esse limite e o desenvolvedor principal sugeriu que os documentos em si foram realmente eliminados (resultado de alguns bugs). Novamente, 4 megas são vários romances de texto.
Gates VP

3
@Gates VP, concordo em usar um mecanismo de texto completo separado. Eu estava pensando em uma pesquisa de metadados. E se você tiver um conjunto de documentos do livro e quiser encontrar todos os livros publicados em 1982? Se cada livro tiver + 100kb de texto, você não deseja transferir vários megabytes apenas para exibir os 20 primeiros títulos de livros.
precisa saber é o seguinte

0

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

Se você espera que uma postagem no blog ultrapasse o limite de 16Mb de documento, extraia os comentários em uma coleção separada e faça referência à publicação no comentário e faça uma associação no nível do aplicativo.

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

// comments
[
  {
    text: 'a comment'
    post: ObjectID('AAAA')
  },
  {
    text: 'another comment'
    post: ObjectID('AAAA')
  }
]
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.