Todos os produtos
Search
Central de documentação

ApsaraDB for MongoDB:Planos de consulta e replanejamento de consultas

Última atualização: Jul 20, 2026

Entenda o funcionamento dos planos de consulta do MongoDB, os motivos do replanejamento e como resolver problemas relacionados.

Planejador de consultas

O planejador de consultas do MongoDB seleciona e armazena em cache o plano mais eficiente para cada consulta com base nos índices disponíveis.

image

O planejador avalia os planos candidatos pela quantidade de unidades de trabalho (works) necessárias e armazena o plano vencedor em cache. As entradas em cache são reutilizadas para consultas com o mesmo formato.

As entradas do cache de plano possuem três estados:

  • Ausente (Missing): Não existe nenhum plano no cache.

  • Inativo (Inactive): O plano existe no cache com um valor works avaliado e pode ser promovido a ativo.

  • Ativo (Active): Representa o plano vencedor no cache. Pode ser rebaixado para inativo.

O cache de plano reside na memória e não persiste em disco. Ele é limpo quando a instância do MongoDB reinicia ou quando uma coleção ou índice é excluído. O cache possui limite de tamanho e utiliza evicção LRU.

Use os comandos abaixo para gerencie planos de consulta:

  • Limpe o cache de plano de uma coleção.

    db.<collection>.getPlanCache().clear()
  • Liste todos os formatos de consulta de uma coleção.

    db.<collection>.getPlanCache().list()
    Nota

    O método PlanCache.listQueryShapes() está obsoleto desde o MongoDB 4.2. Use PlanCache.list() em seu lugar.

  • Visualize os planos em cache para um formato de consulta específico.

    db.<collection>.getPlanCache().list([{ $match: { "createdFromQuery.query": { "name": "testname" }, "createdFromQuery.sort": { "name": 1 } } }])
    Nota

    O método PlanCache.getPlansByQuery() está obsoleto desde o MongoDB 4.2. Use PlanCache.list() com um estágio $match para filtrar por formato de consulta.

QueryHash e planCacheKey

A partir do MongoDB 4.2, cada formato de consulta recebe um queryHash exclusivo. A chave planCacheKey depende tanto do formato da consulta quanto dos índices disponíveis. Adicionar ou remover um índice compatível com o formato de consulta altera a planCacheKey, mas não modifica o queryHash.

Considere uma coleção de exemplo com os seguintes índices e formatos de consulta:

  • Índices

    db.foo.createIndex( { x: 1 } )
    db.foo.createIndex( { x: 1, y: 1 } )
    db.foo.createIndex( { x: 1, z: 1 }, { partialFilterExpression: { x: { $gt: 10 } } } )
  • Formatos de consulta

    db.foo.explain().find( { x: { $gt: 5 } } )  // Query operation 1
    db.foo.explain().find( { x: { $gt: 20 } } ) // Query operation 2

O terceiro índice atende à consulta 2, mas não à consulta 1; portanto, as duas consultas possuem chaves de cache de plano diferentes. Adicionar o índice {x:1, a:1} atualiza ambas as chaves de cache.

Replanejamento de consultas

À medida que os dados da coleção mudam, um plano de consulta em cache pode se tornar subótimo e exigir adaptação.

Quando uma consulta corresponde a um plano em cache, o planejador o reutiliza diretamente enquanto monitora o desempenho. Caso o plano em cache se torne significativamente menos eficiente (por exemplo, mais de 10 vezes mais lento) que uma alternativa, o planejador interrompe a execução, remove o plano e reavalia todos os candidatos. Esse processo chama-se replanejamento de consulta.

Impacto e soluções

A presença da palavra-chave "replanned":true no log de consultas lentas indica que o planejador não consegue encontrar um plano consistentemente eficaz para um formato de consulta específico.

Exemplo de entrada no log de consultas lentas:

"replanned":true,"replanReason":"cached plan was less efficient than expected: expected trial execution to take X works but it took at least 10X works"

Impactos

  • Degrada o desempenho das consultas.

  • Provoca contenção de locks de mutex e alta utilização da CPU.

Soluções

  • Faça upgrade temporário da especificação da instância para aliviar a carga do banco de dados.

  • Limpe o cache de plano e verifique se o planejador seleciona um plano melhor.

  • Use hint() na aplicação para especifique um índice nas condições de consulta que causam replanejamento:

    db.<collection>.find({a:"ABC"},{b:1,_id:0}).sort({c:1}).hint({ a: 1, c: 1, b: 1} )
    Nota

    Um hint substitui o comportamento padrão do planejador de consultas.

  • Configure um filtro de índice para restringir os índices usados em consultas que disparam replanejamento:

    // Check if the index exists
    db.<collection>.getIndexes()
    
    // Set the index filter
    db.runCommand(
       {
          planCacheSetFilter: "<collection>",
          query: { a: "ABC" },
          projection: { b: 1, _id: 0 },
          sort: { c: 1 },
          indexes: [
             { a: 1, c: 1 , b: 1 }
          ]
       }
    )
    // Remove the previous filter
    db.runCommand(
       {
          planCacheClearFilters: "<collection>"
       }
    )
    Nota
    • Filtros de índice substituem o comportamento padrão do planejador de consultas.

    • Se uma consulta possuir simultaneamente um hint e um filtro de índice, o filtro de índice terá precedência. Use filtros de índice com cautela. Index Filters.

    • O otimizador de consultas utiliza uma varredura de coleção (COLLSCAN) ou o índice especificado em planCacheSetFilter. Se o índice especificado não existir ou estiver oculto, o otimizador recorrerá a uma varredura de coleção, o que pode causar alto uso de CPU e picos de I/O. Antes de executar planCacheSetFilter, use db.<collection>.getIndexes() para verifique se o índice existe. planCacheSetFilter.

  • (Recomendado) Otimize suas consultas e índices para evitar replanejamento.

    Nota

    Hints e filtros de índice são soluções paliativas. Revisar suas consultas, índices e esquema de documentos geralmente produz resultados melhores.

  • (Recomendado) Para instâncias executando a versão principal 4.2 ou 4.4, atualize para a versão secundária mais recente do kernel a fim de reduzir a contenção de locks de mutex (SERVER-40805) ou faça upgrade para a versão principal 5.0 ou 6.0. Atualize a versão secundária do banco de dados. Atualize a versão principal do banco de dados.

Caso nenhuma dessas soluções resolva o problema, envie um ticket para obter suporte técnico.

Documentação relacionada