DBAtlas · Atlas de operações de banco de dados

Plano de execução regrediu (lentidão repentina)

Uma consulta que ontem era rápida está de repente lenta hoje. Geralmente o otimizador mudou para um plano pior. Encontramos a causa raiz entre estatísticas desatualizadas, sensibilidade a parâmetros, crescimento do volume de dados ou uma mudança repentina de plano, e estabilizamos o plano.

O plano realmente mudou, e quando?

Há vários planos (plan_hash/plan_generation) para a mesma consulta, e quando a lentidão começou? Coincide com um deploy, upgrade, mudança de parâmetro ou carga grande de dados recente?

SELECT sql_id, plan_hash_value, executions, ROUND(elapsed_time/GREATEST(executions,1)/1e6,3) AS sec_per_exec, first_load_time
FROM v$sql WHERE sql_id='&sqlid' ORDER BY first_load_time;
  • As estatísticas podem estar desatualizadas
  • A mesma consulta se comporta de forma diferente conforme o parâmetro (sniffing/peeking)
  • O volume de dados cresceu significativamente
  • O plano mudou de repente após um upgrade/flush

As estatísticas estão atualizadas?

O otimizador baseia suas decisões nas estatísticas. Se a data do último analyze for antiga ou o contador de modificações estiver alto, as estimativas podem ter de fato se desviado, o que leva a um plano ruim.

SELECT table_name, num_rows, last_analyzed, stale_stats
FROM dba_tab_statistics WHERE table_name='T';
  • As estatísticas estão desatualizadas/ausentes
  • As estatísticas estão atualizadas, mas o plano continua sensível a parâmetros

Há sensibilidade a parâmetros?

A consulta escolhe e coloca em cache um plano com base no valor do parâmetro da sua primeira execução (parameter sniffing no MSSQL / bind peeking no Oracle). Esse plano pode ser ruim para outros valores com distribuição desigual.

SELECT sql_id, child_number, plan_hash_value, is_bind_sensitive, is_bind_aware
FROM v$sql WHERE sql_id='&sqlid';
  • Sim, o plano alterna entre bom e ruim conforme o parâmetro
  • O plano correto é conhecido, quero fixá-lo de forma permanente

Causa raiz: estatísticas desatualizadas / ausentes

Com base em estatísticas antigas que não correspondem à realidade, o otimizador estimou errado o número de linhas e escolheu um plano ruim. Esta é a causa mais comum de regressão de plano.

Causa raiz: sensibilidade a parâmetros (sniffing / bind peeking)

O plano em cache foi escolhido para o primeiro valor de parâmetro que chegou e é ruim para outros valores com distribuição desigual. O objetivo é garantir que seja escolhido um plano adequado ao valor.

Solução: fixe o plano correto (baseline / force plan)

Se existir um plano bom conhecido, fixá-lo para que o otimizador não se desvie dele interrompe a regressão de forma permanente.

Causa raiz: o volume de dados cresceu e o plano não serve mais

À medida que a tabela cresce, um plano que antes era ideal (ex.: nested loop) passa a escalar mal; o otimizador precisa de estatísticas e caminhos de acesso que reflitam corretamente o crescimento.

Causa raiz: mudança repentina de plano (upgrade / flush do cache)

O plano mudou de repente após um upgrade de versão, uma mudança de parâmetro ou o esvaziamento do plan cache. O comportamento do otimizador ou as condições do ambiente mudaram.

Abrir no DBAtlas →