A otimização de query melhora a eficiência das operações de leitura, reduzindo a quantidade de dados que as operações de query precisam processar. Use índices, projeções e limites de query para melhorar o desempenho da query e reduzir o consumo de recursos.
Crie índices para oferecer suporte a queries
Crie índices para queries comumente emitidas. Se uma query pesquisar vários campos, crie um índice composto. O uso de um índice melhora o desempenho porque, sem um índice, a query deve verificar todos os documento da collection.
Por exemplo, considere a seguinte query no campo type
na collection inventory
:
let typeValue = <someUserInput>; db.inventory.find( { type: typeValue } );
Para melhorar o desempenho desta query, adicione um índice à inventory
collection no type
campo. []1 mongosh
Em, crie índices usando o db.collection.createIndex()
método:
db.inventory.createIndex( { type: 1 } )
Para analisar o desempenho da query, consulte Interpretar os resultados do plano de explicação.
[1] | Para índices de campo único, a ordem do índice não importa. Para índices compostos, a ordem dos campo afeta as consultas suportadas pelo índice. Para obter detalhes, consulte Ordem de classificação do índice composto. |
Criar queries seletivas
A seletividade da query refere-se à eficiência com a qual o predicado da query filtra documentos em uma collection. A seletividade da query determina se as queries podem usar índices de forma eficaz.
Queries mais seletivas correspondem a uma porcentagem menor de documentos. Por exemplo, uma correspondência de igualdade no campo _id
único é altamente seletiva, pois pode corresponder a no máximo um documento.
Queries menos seletivas fazem correspondência de uma porcentagem maior de documentos e não podem usar índices de forma eficaz.
Por exemplo, os operadores de desigualdade $nin
e $ne
não são muito seletivos, pois geralmente correspondem a uma grande parte do índice. Como resultado, em muitos casos, uma query $nin
ou $ne
com um índice pode ter um desempenho não melhor do que uma query $nin
ou $ne
, que deve digitalizar todos os documentos em uma collection.
A seletividade do regular expressions
depende das próprias expressões. Para detalhes, consulte expressão regular e uso de índice.
Somente dados necessários do projeto
Quando você precisa de um subconjunto de campos de documentos, pode melhorar o desempenho retornando somente os campos necessários. As projeções reduzem o tráfego da rede e o tempo de processamento.
Por exemplo, se a sua query para a collection posts
precisar somente dos campos timestamp
, title
, author
e abstract
, especifique esses campos na projeção:
db.posts.find( {}, { timestamp : 1, title : 1, author : 1, abstract : 1} ).sort( { timestamp : -1 } )
Quando você usa um $project
estágio de agregação, ele normalmente deve ser o último estágio do seu pipeline, usado para especificar quais campos devem ser retornados ao cliente.
É improvável que o uso de um estágio $project
no início ou no meio de um pipeline para reduzir o número de campos passados para estágios subsequentes melhore o desempenho, pois o banco de dados executa essa otimização automaticamente.
Para obter mais informações sobre como usar projeções, consulte Campos do projeto a serem retornados da query.
Limitar resultados da consulta
Os cursores do MongoDB retornam resultados em lotes. Se você souber o número de resultados que deseja, especifique este valor no método. Limitar resultados reduz a demanda dos recursos da limit()
rede.
Geralmente, limitar resultados é mais útil quando os resultados são classificados para que você saiba quais documentos serão retornados. Por exemplo, se você precisar de apenas 10 resultados da sua query para a coleção posts
, execute a seguinte query:
db.posts.find().sort( { timestamp : -1 } ).limit(10)
Para obter mais informações sobre como limitar resultados,limit()
consulte.
Usar dicas de índice
O otimizador de query normalmente seleciona o índice ideal para uma operação específica. No entanto, você pode forçar o MongoDB a usar um índice específico usando o hint()
método. Use para oferecer suporte ao teste de desempenho ou quando estiver consultando um campo que aparece em vários índices para garantir que o MongoDB use o índice hint()
correto.
Usar operações do lado do servidor
Use o operador do MongoDB $inc
para aumentar ou diminuir valores em documentos. O operador incrementa o valor do campo no lado do servidor , como uma alternativa para selecionar um documento, fazer modificações simples no cliente e, em seguida, gravar o documento inteiro no servidor. O operador também pode ajudar a evitar condições de corrida que ocorrem quando duas instâncias de aplicação fazem query de um documento, incrementam manualmente um campo e salvam o documento inteiro ao mesmo $inc
tempo.
Executar queries cobertas
Uma query coberta é uma query que pode ser satisfeita inteiramente usando um índice e não precisa examinar nenhum documento. Um índice cobre uma query quando todas as opções a seguir se aplicam:
Todos os campos na query (conforme especificados pelo aplicativo e conforme necessários internamente, como para fins de fragmentação) fazem parte de um índice.
todos os campos retornados nos resultados estão no mesmo índice.
Nenhum campo na query é igual a
null
. Por exemplo, os seguintes predicados de query não podem resultar em queries cobertas:{ "field": null }
{ "field": { $eq: null } }
Exemplo
Uma coleção inventory
tem o seguinte índice nos campos type
e item
:
db.inventory.createIndex( { type: 1, item: 1 } )
O índice abrange a seguinte operação que executa queries nos campos type
e item
e retorna apenas o campo item
:
db.inventory.find( { type: "food", item:/^c/ }, { item: 1, _id: 0 } )
Para o índice especificado cobrir a query, o documento de projeção deve especificar explicitamente _id: 0
para excluir o campo _id
do resultado, já que o índice não inclui o campo _id
.
Documentos incorporados
Um índice pode cobrir uma query em campos dentro de documentos incorporados.
Por exemplo, considere uma coleção userdata
com documentos do seguinte formato:
db.userdata.insertOne( { _id: 1, user: { login: "tester" } } )
A collection tem o seguinte índice:
db.userdata.createIndex( { "user.login": 1 } )
O índice { "user.login": 1 }
abrange a seguinte query:
db.userdata.find( { "user.login": "tester" }, { "user.login": 1, _id: 0 } )
Observação
Para indexar campos em documentos incorporados, use notação de ponto. Consulte Criar um índice em um campo incorporado.
Cobertura de múltiplas chaves
Os índices de múltiplas chaves podem cobrir queries sobre os campos que não são da array se o índice acompanhar qual(is) campo(s) faz(em) com que o índice seja de múltiplas chaves.
Os índices com várias chaves não podem cobrir queries em campos de array.
Para obter um exemplo de uma query coberta com um índice multichave, consulte Queries cobertas na página de índices multichave.
Desempenho
Como o índice contém todos os campos exigidos pela query, o MongoDB pode corresponder às condições da query e retornar os resultados usando apenas o índice.
Uma query apenas do índice pode ser muito mais rápido do que uma query de documentos fora do índice. As chaves de índice são normalmente menores do que os documentos que elas catalogam, e os índices geralmente estão disponíveis na RAM ou localizados sequencialmente no disco.
Limitações
Tipos de índice
Nem todos os tipos de índice podem cobrir queries. Para obter detalhes sobre o suporte ao índice coberto, consulte a página de documentação para o tipo de índice correspondente.
Coleções fragmentadas
Ao executar no mongos
, os índices somente podem cobrir queries em collections fragmentadas se o índice contiver a chave de shard.
Explicação de resultados
Para determinar se uma query é uma query coberta, utilize o método db.collection.explain()
ou explain()
. Consulte Queries cobertas.