Query lenta é sintoma, não doença. Antes de "jogar um índice" no problema, você precisa entender o que o PostgreSQL está fazendo de fato. Este guia mostra como investigar.
Passo 1: identifique as queries lentas
Habilite o log de queries lentas no postgresql.conf:
-- Loga queries que levam mais de 200ms
ALTER SYSTEM SET log_min_duration_statement = 200;
SELECT pg_reload_conf();Ou use a extensão pg_stat_statements:
CREATE EXTENSION pg_stat_statements;
SELECT query, calls, mean_exec_time, total_exec_time
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 20;Passo 2: EXPLAIN ANALYZE
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT o.id, o.total, c.name
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.status = 'pending'
AND o.created_at > NOW() - INTERVAL '30 days'
ORDER BY o.created_at DESC
LIMIT 50;O que procurar no resultado:
- Seq Scan em tabelas grandes — provavelmente falta um índice
- Nested Loop com tabela grande no inner — considere Hash Join
- Sort com alto custo — índice na coluna de ordenação pode ajudar
- Buffers shared read alto — dados não estão em cache
Passo 3: crie o índice certo
Não crie índices genéricos. Crie índices que atendam à query específica:
-- Índice composto para a query acima
CREATE INDEX idx_orders_status_created
ON orders (status, created_at DESC)
WHERE status = 'pending';O índice parcial (WHERE status = 'pending') é menor e mais rápido porque ignora registros que não importam para essa query.
Passo 4: monitore
Após aplicar a correção, compare:
-- Antes: Seq Scan, 450ms
-- Depois: Index Scan, 3msErros comuns
- Índice em coluna de baixa cardinalidade — um índice na coluna
statuscom 3 valores distintos raramente ajuda - Muitos índices — cada índice torna INSERTs e UPDATEs mais lentos
- Não rodar ANALYZE — o planner usa estatísticas desatualizadas
- Ignorar o BUFFERS — a query pode ser rápida mas consumir muita memória
Performance de banco é uma das áreas onde vemos mais desperdício. Na NexCript, incluímos auditoria de queries em todo projeto que envolve PostgreSQL.