Otimização de Bancos de Dados Relacionais: Índices B-Tree, Explain Analyze e Eliminação de Queries Lentas
O sistema estava rápido no lançamento, mas, com o crescimento dos dados, telas começam a demorar segundos para abrir e relatórios travam. Na grande maioria dos casos, a causa está em algumas poucas consultas ao banco de dados sem os índices certos. Este guia mostra como encontrar essas consultas no MySQL e no PostgreSQL, ler o plano de execução e corrigir com índices e ajustes simples.
Passo 1: encontre as consultas lentas
MySQL
Ative o slow query log, que registra consultas acima de um tempo definido:
SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1;
Depois, analise o arquivo de log com a ferramenta mysqldumpslow ou consulte o performance_schema.
PostgreSQL
Ative a extensão pg_stat_statements (incluindo-a em shared_preload_libraries e criando a extensão) e consulte as mais custosas:
SELECT query, calls, mean_exec_time, total_exec_time FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 10;
Comece pelas consultas com maior tempo total: uma consulta de 50 ms chamada 100 mil vezes pesa mais que uma de 5 segundos chamada uma vez.
Passo 2: leia o plano de execução
Coloque EXPLAIN ANALYZE antes da consulta. O banco executa e mostra como buscou os dados:
EXPLAIN ANALYZE SELECT * FROM pedidos WHERE cliente_id = 123 ORDER BY criado_em DESC;
Sinais de problema:
- Seq Scan (PostgreSQL) ou type: ALL (MySQL) em tabelas grandes: o banco está lendo a tabela inteira.
- Linhas estimadas muito diferentes das reais: as estatísticas estão desatualizadas.
- Sort ou Using filesort sobre muitas linhas: falta índice para a ordenação.
Passo 3: crie os índices certos
Índices B-Tree, o tipo padrão, funcionam como o índice de um livro: permitem achar linhas sem ler tudo.
CREATE INDEX idx_pedidos_cliente_data ON pedidos (cliente_id, criado_em);
Regras práticas:
- Índice composto: coloque primeiro as colunas usadas com igualdade (=) e depois as de intervalo ou ordenação.
- Colunas de JOIN: chaves estrangeiras quase sempre precisam de índice.
- Não exagere: cada índice deixa inserções e atualizações mais lentas e ocupa espaço. Crie com base em consultas reais.
- No PostgreSQL em produção, use
CREATE INDEX CONCURRENTLYpara não bloquear a tabela.
Passo 4: corrija padrões que anulam índices
- Funções na coluna:
WHERE DATE(criado_em) = '2026-10-10'impede o uso do índice. Use intervalo:criado_em >= '2026-10-10' AND criado_em < '2026-10-11'. - LIKE com curinga no início:
LIKE '%silva'não usa índice B-Tree. Para busca de texto, use recursos de busca textual. - SELECT *: traga só as colunas necessárias.
- Problema N+1: o sistema faz uma consulta por item de uma lista. Troque por uma única consulta com JOIN ou IN. É um dos problemas mais comuns em sistemas com ORM.
- Paginação com OFFSET alto:
OFFSET 100000lê e descarta 100 mil linhas. Prefira paginação por chave (WHERE id > último_id).
Passo 5: manutenção do banco
- Estatísticas: rode
ANALYZE(PostgreSQL) ouANALYZE TABLE(MySQL) depois de grandes cargas de dados. - VACUUM no PostgreSQL: o autovacuum precisa estar ativo e acompanhando o volume de alterações.
- Memória: ajuste
innodb_buffer_pool_size(MySQL) oushared_buffersework_mem(PostgreSQL) de acordo com a RAM do servidor. - Conexões: use um pool de conexões em vez de abrir uma nova a cada requisição.
Antes de comprar um servidor maior
Aumentar o servidor resolve temporariamente, mas consultas sem índice continuam piorando conforme os dados crescem. Um índice certo costuma transformar segundos em milissegundos. Monitore, corrija as consultas mais pesadas e só então avalie hardware. Para manutenção do servidor, veja manutenção preventiva, e para lentidão do lado do site, por que seu site está lento.
Consultoria Backend PruPru
Desenvolvemos sistemas backend robustos em Java (Spring Boot) e Node.js com arquitetura de banco de dados ultra-otimizada.
Falar com o Desenvolvedor →Perguntas frequentes
Como descobrir quais consultas estão lentas?
No MySQL, ative o slow query log. No PostgreSQL, use a extensão pg_stat_statements. Comece pelas consultas com maior tempo total acumulado.
Criar muitos índices deixa o banco mais rápido?
Não necessariamente. Índices aceleram leituras, mas deixam inserções e atualizações mais lentas e ocupam espaço. Crie índices com base nas consultas reais do sistema.
O que o EXPLAIN ANALYZE mostra?
Mostra como o banco executou a consulta: se usou índices ou leu a tabela inteira, quantas linhas processou e quanto tempo cada etapa levou.