Como otimizar queries lentas no PostgreSQL
Aprenda técnicas práticas para identificar e resolver gargalos de performance em suas consultas PostgreSQL.
Por que queries lentas são um problema crítico?
Queries lentas são um dos principais desafios em aplicações que escalam. Uma consulta mal otimizada pode impactar diretamente a experiência do usuário, aumentar custos de infraestrutura e até derrubar sua aplicação em momentos de pico.
1. Identificando queries lentas
O primeiro passo é identificar quais queries estão causando problemas. O PostgreSQL oferece ferramentas nativas para isso:
Usando pg_stat_statements
-- Ative a extensão
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- Consulte as queries mais lentas
SELECT
query,
calls,
total_exec_time,
mean_exec_time,
max_exec_time
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 20;
EXPLAIN ANALYZE
Para entender o que está acontecendo em uma query específica, use EXPLAIN ANALYZE:
EXPLAIN ANALYZE
SELECT * FROM orders
WHERE customer_id = 123
AND created_at > '2026-01-01';
2. Principais causas de queries lentas
Falta de índices apropriados
A causa mais comum de queries lentas é a ausência de índices nas colunas usadas em WHERE, JOIN e ORDER BY.
-- Crie índices nas colunas mais consultadas
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
CREATE INDEX idx_orders_created_at ON orders(created_at);
-- Para queries com múltiplas condições, considere índices compostos
CREATE INDEX idx_orders_customer_created ON orders(customer_id, created_at);
N+1 Queries
O problema N+1 ocorre quando você executa uma query para buscar registros principais e depois uma query adicional para cada registro. Use JOINs ou window functions para resolver:
-- ❌ Ruim: N+1 queries
SELECT * FROM customers;
-- Depois: SELECT * FROM orders WHERE customer_id = ?
-- ✅ Bom: Uma única query com JOIN
SELECT c.*, o.*
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id;
Queries sem LIMIT
Sempre use LIMIT quando possível, especialmente em tabelas grandes:
-- Adicione paginação
SELECT * FROM logs
ORDER BY created_at DESC
LIMIT 100 OFFSET 0;
3. Técnicas avançadas de otimização
Índices parciais
Crie índices apenas para um subconjunto dos dados:
-- Índice apenas para pedidos ativos
CREATE INDEX idx_orders_active ON orders(created_at)
WHERE status = 'active';
Materialized Views
Para queries complexas executadas frequentemente:
CREATE MATERIALIZED VIEW sales_summary AS
SELECT
customer_id,
COUNT(*) as total_orders,
SUM(amount) as total_spent
FROM orders
GROUP BY customer_id;
-- Refresque periodicamente
REFRESH MATERIALIZED VIEW sales_summary;
Vacuum e Analyze
Mantenha as estatísticas do PostgreSQL atualizadas:
-- Execute regularmente
VACUUM ANALYZE orders;
-- Configure autovacuum no postgresql.conf
autovacuum = on
autovacuum_vacuum_scale_factor = 0.1
4. Monitoramento contínuo
Configure alertas para queries lentas usando ferramentas como:
- pgBadger: Análise de logs do PostgreSQL
- pg_stat_statements: Estatísticas de queries em tempo real
- CloudPG Dashboard: Monitoramento integrado de performance
Conclusão
Otimizar queries é um processo contínuo. Use as ferramentas nativas do PostgreSQL, monitore constantemente e sempre teste mudanças em ambientes de staging antes de produção. Com essas técnicas, você pode reduzir drasticamente o tempo de resposta das suas aplicações.
Próximos passos
Quer colocar essas técnicas em prática? Crie sua instância PostgreSQL grátis no CloudPG e experimente todas essas otimizações em um ambiente gerenciado com ferramentas de monitoramento integradas.