Como a projeção do mongoDB afeta o desempenho?

10

Na MongoDBdocumentação , é mencionado que:

Quando você precisa apenas de um subconjunto de campos de documentos, pode obter um melhor desempenho retornando apenas os campos necessários

Como os campos de filtragem afetam o desempenho? O desempenho está relacionado ao tamanho dos dados transmitidos pela rede? ou o tamanho dos dados que serão retidos na memória? Como exatamente esse desempenho é aprimorado? Qual é esse desempenho mencionado na documentação?

Tenho consultas lentas do MongoDB. O retorno de um subconjunto afeta minha consulta lenta (tenho índice composto no campo)?

ALH
fonte
Sem o código, não é possível sugerir você. o que realmente afetará o desempenho na consulta de projeção "MongoDB". É sempre melhor, pelo menos, você mencionar o código.
Md Haidar Ali Khan
@MdHaidarAliKhan não é sobre o código e minha carga útil. Eu só quero saber por que o mongoDB diz que a filtragem afeta o desempenho? De que ponto de vista esse desempenho foi medido? Por exemplo, ajuda no uso de memória do Mongo devido a menos dados ou menos IO de disco (por exemplo) e assim por diante.
ALH
Eu só quero saber por que o mongoDB diz que a filtragem afeta o desempenho? bem, use as projeções para retornar apenas os dados necessários. Quero dizer que você pode obter melhor desempenho retornando apenas os campos necessários. Por exemplo, db.posts.find ({}, {}). Sort ({}).
Md Haidar Ali Khan
Por exemplo, ajuda no uso da memória do Mongo por causa de menos dados ou menos E / S de disco (por exemplo) e assim por diante, bem ... você pode atualizar qual versão do MongoDB e sistema operacional em seu ambiente?
Md Haidar Ali Khan
@MdHaidarAliKhan OS é Debian 8,MongoDB 3.6.2
ALH

Respostas:

15

Por padrão, as consultas retornam todos os campos nos documentos correspondentes. Se você precisar de todos os campos, o retorno de documentos completos será mais eficiente do que o servidor manipular o conjunto de resultados com critérios de projeção.

No entanto, o uso da projeção para limitar os campos a serem retornados dos resultados da consulta pode melhorar o desempenho:

  • removendo campos desnecessários dos resultados da consulta (economizando largura de banda da rede)
  • limitando os campos de resultados para obter uma consulta coberta (retornando resultados da consulta indexada sem buscar documentos completos)

Ao usar a projeção para remover campos não utilizados, o servidor MongoDB precisará buscar cada documento completo na memória (se ainda não estiver lá) e filtrar os resultados para retornar. Esse uso da projeção não reduz o uso da memória ou o conjunto de trabalho no servidor MongoDB, mas pode economizar largura de banda de rede significativa para os resultados da consulta, dependendo do modelo de dados e dos campos projetados.

Uma consulta coberta é um caso especial em que todos os campos solicitados em um resultado da consulta são incluídos no índice usado, para que o servidor não precise buscar o documento completo. As consultas cobertas podem melhorar o desempenho (evitando a busca de documentos) e o uso de memória (se outras consultas não exigirem a busca do mesmo documento).

Exemplos

Para fins de demonstração via mongoshell, imagine que você tenha um documento parecido com este:

db.data.insert({
    a: 'webscale',
    b: new Array(10*1024*1024).join('z')
})

O campo bpode representar uma seleção de valores (ou, nesse caso, uma sequência muito longa).

Em seguida, crie um índice no {a:1}qual é um campo comumente usado pelo seu caso de uso:

db.data.createIndex({a:1})

Um simples findOne()sem critério de projeção retorna um resultado de consulta de aproximadamente 10 MB:

> bsonsize(db.data.findOne({}))
10485805

A adição da projeção {a:1}limitará a saída ao campo ae ao documento _id(que é incluído por padrão). O servidor MongoDB ainda está manipulando um documento de 10 MB para selecionar dois campos, mas o resultado da consulta agora é de apenas 33 bytes:

> bsonsize(db.data.findOne({}, {a:1}))
33

Esta consulta não é coberta porque o documento completo precisa ser buscado para descobrir o _idvalor. O _idcampo é incluído nos resultados da consulta por padrão, pois é o identificador exclusivo de um documento, mas _idnão será incluído em um índice secundário, a menos que seja explicitamente adicionado.

As métricas totalDocsExaminede totalKeysExaminednos explain()resultados mostrarão quantos documentos e chaves de índice foram examinados:

 > db.data.find(
     {a:'webscale'}, 
     {a:1}
 ).explain('executionStats').executionStats.totalDocsExamined
 > 1

Essa consulta pode ser aprimorada usando a projeção para excluir o _idcampo e obter uma consulta coberta usando apenas o {a:1}índice. A consulta coberta não precisa mais buscar um documento de ~ 10 MB na memória; portanto, será eficiente no uso da rede e da memória:

 > db.data.find(
     {a:'webscale'},
     {a:1, _id:0}
 ).explain('executionStats').executionStats.totalDocsExamined
 0

 > bsonsize(db.data.findOne( {a:'webscale'},{a:1, _id:0}))
 21

Tenho consultas lentas do MongoDB. O retorno de um subconjunto afeta minha consulta lenta (tenho índice composto no campo)?

Isso não pode ser respondido sem o contexto de uma consulta específica, um exemplo de documento e a saída completa da explicação. No entanto, você pode executar alguns benchmarks em seu próprio ambiente para a mesma consulta com e sem projeção para comparar o resultado. Se sua projeção está adicionando uma sobrecarga significativa ao tempo geral de execução da consulta (processamento e transferência de resultados), isso pode ser uma forte dica de que seu modelo de dados pode ser aprimorado.

Se não estiver claro por que uma consulta é lenta, seria melhor postar uma nova pergunta com detalhes específicos para investigar.

Stennie
fonte
11
Eu realmente aprecio a explicação completa do problema. Parece que não é possível ter consultas cobertas, pois minha resposta tem muito mais dados do que dentro do índice. Minha principal pergunta é aqui, eu ficaria feliz se você pudesse dar uma olhada: dba.stackexchange.com/questions/195065/…
ALH
1

Com uma projeção, você pode alcançar uma situação em que o conjunto de resultados vem diretamente do índice.

Se você tiver um índice composto em {x:1, y:1, z:1}que nenhum de x, y, z é _id, será necessário projetar {_id:0, x:1, y:1, z:1}porque _idsempre é retornado como parte do conjunto de resultados (quando não é projetado para fora) e o mecanismo precisa ler os arquivos de dados para obtê-lo. Isso porque, o índice não tem o valor de _id, apenas o ponteiro para o documento em que o valor está armazenado.

JJussi
fonte
Portanto, se eu remover _idda resposta retornada, isso cabe na RAM? Isso ajuda?
ALH
11
O MongoD (tenta) manter pelo menos índices na memória (e quantos dados couberem). Se a sua consulta puder ser preenchida diretamente do índice e o projeto _id:0, o resultado será retornado totalmente da RAM, sem a leitura de dados do disco.
21418 JJussi