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

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.

Abrir no DBAtlas →