Consulta lenta: diagnóstico aprofundado
Uma consulta ou o sistema inteiro está lento. Restrinja passo a passo: rode uma verificação em cada nó e escolha o ramo com base no resultado. No fim, você chega a uma causa raiz + correção.
O que está lento?
Uma ou algumas consultas específicas estão lentas, ou o sistema inteiro? Isso divide a investigação em uma de duas trilhas: 'focada na query' ou 'focada em recursos/gargalo'.
- Uma ou algumas consultas específicas estão lentas
- O sistema inteiro está lento
A consulta está rodando agora?
É uma consulta rodando/travada agora ou uma que é 'lenta em geral'? Olhe as sessões ativas.
SELECT sid, serial#, sql_id, last_call_et AS running_sec, event, blocking_session
FROM v$session WHERE status='ACTIVE' AND type='USER' ORDER BY last_call_et DESC;- Rodando / travada agora
- Lenta em geral; quero olhar o plano
A consulta está esperando por algo?
Se está ativa mas não progride, muito provavelmente está esperando. blocking_session / wait_event está preenchido?
SELECT sid, blocking_session, event, seconds_in_wait
FROM v$session WHERE sid=&target_sid;- Bloqueada por outra sessão
- Esperando por um recurso (IO / log / latch)
- Sem espera; consumindo CPU ativamente
Qual espera predomina?
O wait event predominante indica o tipo de gargalo.
SELECT event, total_waits, time_waited FROM v$session_event WHERE sid=&target_sid ORDER BY time_waited DESC FETCH FIRST 5 ROWS ONLY;- Espera de IO (db file read / PAGEIOLATCH)
- Espera de log / commit (log file sync / WRITELOG)
- Lock / enqueue (enq: TX / LCK)
Obter o plano de execução (EXPLAIN)
Obtenha o plano. Há um full table scan, uma ordem de join inesperada ou uma diferença entre linhas estimadas e reais?
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id', NULL, 'ALLSTATS LAST'));- Full scan / índice faltante
- Era rápida ontem; o plano mudou de repente
- Processa linhas demais / N+1
- O plano parece bom, mas está lenta
As estatísticas estão atualizadas?
Uma grande diferença entre linhas estimadas e reais (E-rows vs A-rows) é sinal de estatísticas desatualizadas.
SELECT table_name, num_rows, last_analyzed FROM dba_tables WHERE table_name='&TABLE_NAME';- As estatísticas estão desatualizadas / antigas
- As estatísticas estão atualizadas, mas continua lenta
No sistema inteiro: onde está o gargalo?
Se tudo está lento, e não uma única consulta, procure um gargalo de recurso: CPU, IO, memória ou bloqueio generalizado?
SELECT metric_name, value FROM v$sysmetric WHERE metric_name IN ('Host CPU Utilization (%)','Average Active Sessions') AND intsize_csec=(SELECT MAX(intsize_csec) FROM v$sysmetric);- CPU perto de 100%
- Espera de IO alta
- Pressão de memória / cache hit baixo
- Muito bloqueio
Causa raiz: bloqueio
A consulta está esperando por um lock mantido por outra sessão. Encontre a sessão no início da cadeia (root blocker) e resolva-a.
Causa raiz: gargalo de IO
A consulta lê muito do disco. Geralmente por causa de full scans (índice faltante) ou memória insuficiente (buffer cache).
Causa raiz: gargalo de commit / log
Se 'log file sync' / 'WRITELOG' predomina, os commits estão esperando as escritas de redo/WAL.
Causa raiz: índice faltante
O plano faz um full scan. Um índice adequado nas colunas de filtro/join dá um grande ganho de velocidade.
Causa raiz: regressão de plano
A consulta era rápida ontem, mas hoje não; o plano mudou. Geralmente por estatísticas desatualizadas ou mudança de parâmetro.
Causa raiz: design da consulta
O plano é razoável, mas a consulta em si faz trabalho demais (linhas demais, N+1, joins desnecessários).
Causa raiz: estatísticas desatualizadas
O otimizador erra as estimativas porque as estatísticas não estão atualizadas.
Análise aprofundada
Se o plano e as estatísticas estão bons, mas continua lento, aprofunde.
Causa raiz: gargalo de CPU
O sistema inteiro está limitado por CPU. Geralmente algumas consultas mal planejadas estão consumindo a CPU.
Causa raiz: pressão de memória
Cache hit baixo e/ou swap: a memória é insuficiente ou está mal alocada.