Learn the "why" behind slow queries and how to fix them in our 2-Part Webinar.
Register now >
Menu Docs
Página inicial do Docs
/ /

Otimização de Consulta

A otimização de query reduz a quantidade de dados que uma query deve processar. Use índices, projeções e limites de query para melhorar o desempenho e reduzir o consumo de recursos. Revise o desempenho da query periodicamente à medida que as coleções crescem para determinar quando devem ser dimensionadas.

Os índices armazenam valores de campo em uma estrutura de dados separada. Em operações de leitura, o MongoDB pesquisa o índice em vez de fazer a varredura de toda a coleção. Nas operações de gravação, o MongoDB atualiza a coleção e o índice.

Crie índices para suas queries mais comuns. Se uma query pesquisar vários campos, crie um índice composto.

Por exemplo, considere a seguinte query no campo type na collection inventory:

let typeValue = <someUserInput>;
db.inventory.find( { type: typeValue } );

Para melhorar o desempenho nesta consulta, adicione um índice no campo type.

db.inventory.createIndex( { type: 1 } )

[1] Em mongosh, utilize db.collection.createIndex():

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.

A seletividade da query mede a eficiência com que um predicado de query filtra documentos e determina se as queries podem usar índices de forma eficaz.

  • Queries altamente seletivas correspondem a menos documentos e usam índices de forma mais eficaz. Por exemplo, uma correspondência de igualdade em _id é altamente seletiva, pois pode corresponder a no máximo um documento.

  • Queries menos seletivas correspondem a mais documentos e usam índices com menos eficiência.

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 de um regular expression depende da própria expressão . Para detalhes, consulte expressão regular e uso de índice.

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, considere a seguinte query para retornar somente os campos timestamp, title, author e abstract.

db.posts.find(
{},
{ timestamp : 1, title : 1, author : 1, abstract : 1}
).sort( { timestamp : -1 } )

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, consulte Campos do projeto a serem retornados da query.

Para obter uma consulta coberta, indexe os campos projetados. A regra ESR (Equality, Sort, faixa) se aplica à ordem dos campos no índice.

Por exemplo, considere o seguinte índice na coleção inventory:

db.inventory.createIndex( { type: 1, _id: 1, price: 1, item: 1, expiryDate: 1} )

A query acima, embora seja técnicamente correta, não está estruturada para otimizar o desempenho da query.

A seguinte query aplica a regra ESR para um índice composto mais eficiente:

db.inventory.aggregate([
{ $match: {type: "food", expiryDate: { $gt: ISODate("2025-07-10T00:00:00Z") }}},
{ $sort: { item: 1 }},
{ $project: { _id: 1, price: 1} }
])

O índice e a query seguem a regra ESR:

  • type é usado para uma correspondência de igualdade (E), portanto, é o primeiro campo no índice.

  • item é usado para classificar (S), então é depois de type no índice.

  • expiryDate é usado para uma consulta de intervalo (R), portanto, é o último campo no índice.

MongoDB cursores retornam resultados em lotes. Se você souber de quantos resultados precisa, passe esse valor para o método limit() para reduzir o uso de recursos da rede.

Limite os resultados após a classificação para saber quais documentos serão devolvidos. Por exemplo, a seguinte query retorna somente os 10 resultados mais recentes da coleção posts:

db.posts.find().sort( { timestamp : -1 } ).limit(10)

Para mais informações, consulte limit().

O otimizador de query seleciona o índice ideal para uma operação específica. No entanto, você pode forçar um índice específico utilizando o método hint(). Isso é útil para testes de desempenho ou quando um campo aparece em vários índices e você precisa garantir qual índice o MongoDB usa.

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 modificações simples no lado do cliente e, em seguida, gravar o documento no servidor. Além disso, o operador evita condições de corrida quando várias instâncias do aplicativo atualizam o mesmo campo simultaneamente.

Uma query coberta é uma query que pode ser satisfeita inteiramente por um índice sem ter que examinar nenhum documento. Um índice cobre uma query quando todas as condições a seguir são verdadeiras:

  • Todos os campos na query (incluindo campos especificados pelo aplicativo e quaisquer campos necessários internamente, como para fragmentação) fazem parte do í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 } }

Uma coleção inventory tem o seguinte índice nos campos type e item:

db.inventory.createIndex( { type: 1, item: 1 } )

O índice cobre a seguinte query, que filtra type e item e retorna apenas 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 .

Um índice pode cobrir uma query em campos dentro de documentos incorporados.

Por exemplo, considere a seguinte coleção userdata:

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.

Os índices de múltiplas chaves podem cobrir queries sobre campos que não são da array se o índice acompanhar qual campo ou campos o torna multichave.

Os índices com várias chaves não podem cobrir queries em campos de array.

Para ver um exemplo, consulte Queries de query na página de índices multichave.

As queries cobertas correspondem às condições da query e retornam resultados usando apenas o índice. Isso é mais rápido do que buscar documentos porque as chaves de índice normalmente são menores que os documentos, e os índices geralmente estão na RAM ou armazenados sequencialmente no disco.

Nem todos os tipos de índice suportam queries cobertas. Consulte a documentação do tipo de índice específico.

Ao executar no mongos, os índices somente podem cobrir queries em collections fragmentadas se o índice contiver a chave de shard.

Para verificar se uma query está coberta, use db.collection.explain() ou explain(). Consulte queries cobertas.

Voltar

Consistência causal e write and read concerns

Receber um selo de habilidade

Domine "Otimização de Consultas" gratuitamente!

Saiba mais

Nesta página