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 mongo
shell, imagine que você tenha um documento parecido com este:
db.data.insert({
a: 'webscale',
b: new Array(10*1024*1024).join('z')
})
O campo b
pode 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 a
e 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 _id
valor. O _id
campo é incluído nos resultados da consulta por padrão, pois é o identificador exclusivo de um documento, mas _id
não será incluído em um índice secundário, a menos que seja explicitamente adicionado.
As métricas totalDocsExamined
e totalKeysExamined
nos 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 _id
campo 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.