O que são estatísticas e por que elas mandam no plano
Quando você executa uma consulta, o otimizador precisa escolher um plano: qual caminho usar para encontrar linhas, em que ordem aplicar filtros, e como juntar tabelas. Para decidir, ele depende de estatísticas: resumos numéricos sobre os dados (e não os dados em si). O objetivo é estimar quantas linhas cada etapa vai produzir e quanto custará ler e combinar essas linhas.
As estatísticas normalmente tentam responder perguntas como:
- Cardinalidade estimada: quantas linhas vão passar por um filtro (ex.:
status = 'PAGO')? - Distribuição: os valores são uniformes ou concentrados em poucos valores?
- Quantidade de valores distintos (frequentemente chamada de NDV): quantos valores diferentes existem em uma coluna?
- Frequência de valores comuns: existem “valores quentes” que aparecem muito?
- Correlação/ordenação: os valores seguem algum padrão físico/lógico (por exemplo, datas inseridas em ordem)?
Com isso, o otimizador compara alternativas como: ler muita coisa e filtrar depois, ou localizar um subconjunto e então buscar o restante; e também escolhe estratégias de junção (por exemplo, qual tabela deve ser a “externa” e qual deve ser a “interna” em um loop).
Estimativa vs. realidade: onde nasce o “plano errado”
O plano escolhido pode parecer “errado” quando a estimativa (o que o otimizador acha que vai acontecer) diverge muito da realidade (o que acontece de fato). O otimizador não é adivinho: ele faz contas com base em estatísticas e suposições. Se as entradas estiverem ruins (estatísticas desatualizadas) ou se as suposições não se aplicarem (dados com correlação forte), o custo calculado pode apontar para um caminho que, na prática, é mais lento.
Um jeito simples de visualizar: se o otimizador acredita que um filtro retorna 10 linhas, ele tende a escolher estratégias que funcionam bem para poucos resultados. Se na prática retornam 1.000.000, a mesma estratégia pode virar um desastre.
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
Como estatísticas influenciam decisões comuns
1) Varredura completa vs. acesso direcionado
Mesmo sem entrar em detalhes de estruturas de índice (já vistas antes), a decisão central é: vale a pena localizar poucas linhas ou é melhor ler muita coisa de uma vez? A resposta depende da cardinalidade estimada e do custo de acessar páginas/linhas.
- Se a estimativa diz “poucas linhas”, o otimizador tende a preferir um caminho de busca direcionada.
- Se a estimativa diz “muitas linhas”, ele tende a preferir uma varredura e filtro, porque o custo de “pular” para muitos pontos pode superar o custo de ler sequencialmente.
2) Ordem de junções e estratégia de junção
Em junções, a cardinalidade estimada define:
- Qual tabela filtrar primeiro (para reduzir cedo o volume).
- Qual lado usar como entrada em estratégias que repetem buscas no outro lado.
- Se compensa pré-agrupar ou aplicar filtros antes/depois da junção.
Um erro de estimativa em uma tabela “no começo” do plano se propaga: uma pequena diferença no início pode virar uma diferença enorme no meio do plano.
Fatores que degradam estimativas (e por quê)
1) Estatísticas desatualizadas
Se os dados mudaram muito desde a última coleta/atualização de estatísticas, o otimizador pode estar “enxergando” um passado que não existe mais. Exemplos típicos:
- Uma coluna que antes tinha distribuição uniforme passa a ter concentração (um valor domina).
- Uma tabela cresce 10x e o custo relativo de ler tudo muda.
- Um status raro vira comum após mudança de regra de negócio.
O resultado: o otimizador escolhe um plano que era bom para o cenário antigo, mas não para o atual.
2) Valores atípicos (skew) e “valores quentes”
Muitas estimativas assumem, por padrão, algo próximo de uniformidade: cada valor aparece com frequência parecida. Mas na prática é comum ter skew:
status: 95%'PAGO', 5% outros.pais: um país concentra a maioria dos registros.data: picos em datas específicas (promoções, viradas de mês).
Se as estatísticas não capturam bem esses valores dominantes, uma consulta filtrando pelo valor “quente” pode retornar muito mais linhas do que o estimado. O plano escolhido para “poucas linhas” vira inadequado.
3) Filtros correlacionados entre colunas
Um dos maiores vilões é a suposição de independência: o otimizador frequentemente estima a seletividade de filtros múltiplos como se fossem independentes. Exemplo conceitual:
estado = 'SP'reduz para 20% das linhas.cidade = 'São Paulo'reduz para 1% das linhas.
Se o otimizador assumir independência, pode multiplicar: 0,20 * 0,01 = 0,002 (0,2%). Mas na realidade, cidade = 'São Paulo' praticamente implica estado = 'SP'. Então o segundo filtro não reduz “mais” quase nada além do primeiro; a seletividade real pode ficar perto de 1%, não 0,2%.
Essa diferença parece pequena, mas pode mudar decisões de plano, especialmente em junções e ordenações.
Exemplos conceituais: pequenas diferenças que mudam o plano
Exemplo A: o limiar entre “poucas” e “muitas” linhas
Imagine uma tabela com 10 milhões de linhas e uma consulta:
SELECT * FROM pedidos WHERE status = 'PAGO';Cenário 1 (estimativa otimista): estatísticas sugerem que 'PAGO' retorna 10 mil linhas (0,1%). O otimizador tende a escolher um caminho que funciona bem para poucos resultados.
Cenário 2 (realidade): na prática, 'PAGO' retorna 6 milhões (60%). Agora, o custo de acessar milhões de linhas “espalhadas” pode ser maior do que ler a tabela e filtrar. O plano escolhido no Cenário 1 pode ficar muito pior no Cenário 2.
O ponto-chave: não é preciso errar por 100x para dar problema; às vezes errar de 2x a 5x já cruza um limiar de decisão.
Exemplo B: erro pequeno no começo, explosão no meio
Considere uma junção entre clientes e pedidos com filtros:
SELECT c.id, p.id FROM clientes c JOIN pedidos p ON p.cliente_id = c.id WHERE c.segmento = 'VIP' AND p.data >= '2026-01-01';Se o otimizador estima que segmento = 'VIP' retorna 1.000 clientes, ele pode decidir “para cada cliente, buscar pedidos recentes”. Se na realidade são 50.000 clientes, a mesma estratégia vira 50x mais repetições. Mesmo que cada busca individual seja rápida, o total pode ficar enorme.
Agora note: o erro pode ter vindo de estatísticas desatualizadas (o segmento VIP cresceu) ou de correlação (VIP compra mais e tem mais pedidos recentes, então o filtro de data não reduz tanto quanto o esperado).
Exemplo C: filtros correlacionados mudando a ordem de aplicação
Consulta com dois filtros:
SELECT * FROM entregas WHERE estado = 'SP' AND cidade = 'São Paulo';Se o otimizador acredita que a combinação retorna pouquíssimas linhas (por multiplicação de probabilidades), ele pode escolher um plano que prioriza localizar esse conjunto minúsculo. Se a correlação faz o resultado ser bem maior, um plano alternativo (aplicar um filtro mais “forte” primeiro, ou escolher outra ordem de operações) poderia ser melhor.
Passo a passo prático: como diagnosticar “estimativa ruim” sem depender de um SGBD específico
Passo 1: compare estimado vs. real no plano
Use o recurso do seu banco para visualizar o plano e procure, em cada etapa, algo equivalente a:
- Linhas estimadas (estimated rows)
- Linhas reais (actual rows)
Marque os pontos onde a diferença é grande (por exemplo, 10x, 100x). Normalmente o problema começa em um filtro ou junção específica e se propaga.
Passo 2: identifique o predicado que “quebrou” a estimativa
Para o operador onde a divergência aparece, pergunte:
- O filtro usa uma coluna com distribuição desigual (skew)?
- O filtro envolve múltiplas colunas que podem ser correlacionadas?
- Houve mudança recente de volume (muitas inserções/atualizações)?
Se o erro aparece logo após um WHERE, o suspeito é o filtro. Se aparece após uma junção, o suspeito pode ser a cardinalidade estimada da junção (e não apenas filtros individuais).
Passo 3: valide a distribuição com consultas simples
Sem depender de recursos internos, você pode checar a realidade com agregações:
-- Frequência por valor (detecta skew/valores quentes) SELECT status, COUNT(*) FROM pedidos GROUP BY status; -- Cardinalidade aproximada de um filtro SELECT COUNT(*) FROM pedidos WHERE status = 'PAGO'; -- Correlação entre colunas (exemplo conceitual) SELECT estado, cidade, COUNT(*) FROM entregas GROUP BY estado, cidade;Se você observar que um valor domina ou que combinações específicas concentram volume, isso explica por que a suposição de uniformidade/independência falhou.
Passo 4: observe se o problema é “de hoje”
Compare períodos: se a consulta ficou lenta recentemente, é comum que a distribuição tenha mudado. Exemplos:
- Campanhas que mudam o mix de pedidos.
- Migrações/importações que inserem muitos dados com padrões diferentes.
- Novas regras que alteram o significado de um status.
Isso aponta para estatísticas que não acompanham a realidade atual.
Boas práticas gerais para reduzir planos “errados”
- Mantenha estatísticas atualizadas de acordo com o ritmo de mudança dos dados (tabelas que mudam muito precisam de atenção maior do que tabelas quase estáticas).
- Monitore colunas com skew (valores muito frequentes) porque elas tendem a causar grandes erros de cardinalidade quando a distribuição muda.
- Desconfie de múltiplos filtros correlacionados (ex.: atributos hierárquicos como país/estado/cidade; faixas de data associadas a status; categoria associada a preço). Esses casos são candidatos clássicos a estimativas otimistas demais.
- Reavalie após mudanças grandes de volume (cargas, migrações, viradas de período) porque elas alteram custos relativos e distribuições.
- Use o plano como ferramenta de medição: a diferença entre linhas estimadas e reais é um sinal objetivo de que o otimizador está tomando decisões com base em uma visão distorcida dos dados.