Da MongoDB
documentação é mencionado que:
Quando você precisa apenas de um subconjunto de campos de documentos, pode obter melhor desempenho retornando apenas os campos necessários
Como os campos de filtragem afetam o desempenho? O desempenho está relacionado ao tamanho dos dados que são transmitidos pela rede? ou o tamanho dos dados que serão mantidos na memória? Como exatamente esse desempenho é melhorado? Qual é esse desempenho que está sendo mencionado na documentação?
Eu tenho consultas lentas do MongoDB. O retorno de um subconjunto afeta minha consulta lenta (tenho índice composto no campo)?
Por padrão, as consultas retornam todos os campos nos documentos correspondentes. Se você precisar de todos os campos, retornar documentos completos será mais eficiente do que fazer com que o servidor manipule o conjunto de resultados com critérios de projeção.
No entanto, usar a projeção para limitar os campos a serem retornados dos resultados da consulta pode melhorar o desempenho:
Ao usar a projeção para remover campos não utilizados, o servidor MongoDB terá que buscar cada documento completo na memória (se ainda não estiver lá) e filtrar os resultados a serem retornados. Esse uso de projeção não reduz o uso de memória ou conjunto de trabalho no servidor MongoDB, mas pode economizar largura de banda de rede significativa para resultados de 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 de 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 através do
mongo
shell, imagine que você tenha um documento parecido com este:O campo
b
pode representar uma seleção de valores (ou, neste caso, uma string muito longa).Em seguida, crie um índice no
{a:1}
qual é um campo comumente usado consultado pelo seu caso de uso:Um simples
findOne()
sem critérios de projeção retorna um resultado de consulta com cerca de 10 MB:Adicionar a projeção
{a:1}
limitará a saída ao campoa
e ao documento_id
(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:Essa 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 nos resultados mostrarão quantos documentos e chaves de índice foram examinados:totalKeysExamined
explain()
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:Isso não pode ser respondido sem o contexto de uma consulta específica, documento de exemplo e a saída de explicação completa. 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 estiver adicionando uma sobrecarga significativa ao tempo geral de execução da consulta (processamento e transferência de resultados), isso pode ser um forte indício 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.
Com uma projeção, você pode obter uma situação em que o conjunto de resultados vem diretamente do índice.
Se você tem índice composto
{x:1, y:1, z:1}
onde nenhum de x,y,z é _id, você precisa projetar{_id:0, x:1, y:1, z:1}
porque_id
sempre é retornado como parte do conjunto de resultados (quando não é projetado) e o mecanismo precisa ler arquivos de dados para obtê-lo. Isso porque o índice não tem valor de _id, apenas ponteiro para aquele documento onde o valor está armazenado.