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 rated na collection movies:
let ratingValue = <someUserInput>; db.movies.find( { rated: ratingValue } );
Para melhorar o desempenho desta query, adicione um índice à collection movies no campo rated. [1] Em mongosh, crie índices usando o db.collection.createIndex() método:
db.movies.createIndex( { rated: 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 campos afeta as queries que o índice suporta. Para obter detalhes, consulte Ordem de classificação de índices compostos. |
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 correspondem a 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 movies precisar somente dos campos year, title, directors e plot, especifique esses campos na projeção:
db.movies.find( {}, { year: 1, title: 1, directors: 1 } ).sort( { year: -1 } ).limit(3)
Quando você usa um estágio de agregação $project, 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.
Exemplo
Para obter uma query coberta, você deve indexar campos projetados. A regra ESR (Equality, Sort, Range) se aplica à ordem dos campos no índice.
Por exemplo, considere o seguinte índice em uma coleção movies:
db.movies.createIndex( { rated: 1, _id: 1, "imdb.rating": 1, title: 1, released: 1 } )
O índice anterior, embora seja tecnicamente correto, não está estruturado para otimizar o desempenho da query.
A query a seguir usa a regra ESR (Equality, Sort, faixa) para estruturar um pipeline de agregação mais eficiente e melhorar os tempos de resposta da query.
db.movies.aggregate( [ { $match: { rated: "PG", released: { $gt: ISODate("2000-01-01T00:00:00Z") } } }, { $sort: { title: 1 } }, { $limit: 5 }, { $project: { _id: 1, "imdb.rating": 1 } } ] )
O índice e a query seguem a regra ESR:
ratedé usado para uma correspondência de igualdade (E), portanto, é o primeiro campo no índice.titleé usado para classificar (S), então é depois deratedno índice.releasedé usado para uma consulta de intervalo (R), portanto, é o último campo no índice.
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 limit(). Limitar resultados reduz a demanda dos recursos da rede.
Classifique os resultados antes de aplicar um limite para garantir que a query retorne os documentos esperados. Por exemplo, se você precisar de apenas 10 resultados da sua query para a coleção movies, execute a seguinte query:
db.movies.find( {}, { title: 1, year: 1 } ).sort( { year: -1 } ).limit(10)
Para obter mais informações sobre como limitar resultados, consulte limit().
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 método hint(). Use hint() para oferecer suporte a testes de desempenho ou quando você estiver fazendo uma query em um campo que aparece em vários índices para garantir que o MongoDB use o índice correto.
Usar operações do lado do servidor
Use o operador $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 alterações no código do cliente e, em seguida, gravar o documento inteiro no servidor. O operador $inc também pode ajudar a evitar condições de corrida que ocorrem quando duas instâncias de aplicativo fazem uma query de um documento, incrementam manualmente um campo e salvam o documento inteiro ao mesmo 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 todos os itens 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 movies tem o seguinte índice nos campos rated e title:
db.movies.createIndex( { rated: 1, title: 1 } )
O índice abrange a seguinte operação que executa queries nos campos rated e title e retorna apenas o campo title:
db.movies.find( { rated: "PG", title: /^T/ }, { title: 1, _id: 0 } ).limit(3)
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 a coleção theaters do conjunto de dados sample_mflix, que tem documentos com a seguinte estrutura:
{ theaterId: <num>, location: { address: { street1: "<address>", city: "<city>", state: "<state>", zipcode: "<zip>" }, geo: { ... } } }
A collection tem o seguinte índice:
db.theaters.createIndex( { "location.address.city": 1 } )
O índice { "location.address.city": 1 } abrange a seguinte query:
db.theaters.find( { "location.address.city": "Portland" }, { "location.address.city": 1, _id: 0 } ).limit(1)
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.