Query Optimization no Node.js melhora latência e reduz carga do banco ao combinar SQL adequado, índices, limites, planos de execução e uso correto do pool. Otimização começa medindo consultas reais, não aplicando regras genéricas.
Localize queries caras
Use métricas da aplicação e pg_stat_statements para encontrar alto tempo total, média elevada ou muitas chamadas. Uma query rápida executada milhões de vezes também pode ser prioridade.
EXPLAIN
EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
SELECT id, total
FROM orders
WHERE tenant_id = $1
ORDER BY created_at DESC
LIMIT 50;Analise estimativas, linhas reais, loops, buffers, sorts e scans. Diferenças grandes entre estimado e real podem indicar estatísticas insuficientes ou distribuição desigual.
Selecione apenas o necessário
SELECT id, status, total
FROM orders
WHERE id = $1;Evite SELECT * quando a aplicação precisa de poucas colunas, principalmente com campos JSON ou textos grandes.
Evite N+1
Buscar uma lista e depois executar uma query por item multiplica round trips.
SELECT o.id, o.total, c.name
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.tenant_id = $1;Outra opção é buscar em lote com WHERE id = ANY($1).
Índices alinhados
O índice deve corresponder a filtros, joins e ordenação. Consulte Índices PostgreSQL no Node.js.
Paginação
OFFSET alto exige descartar muitas linhas e pode produzir resultados instáveis durante mudanças. Para listas extensas, prefira cursor.
Prepared statements e parâmetros
Use parâmetros para evitar SQL injection e favorecer reutilização de planos, observando casos em que planos genéricos ficam inadequados para distribuições muito diferentes.
Timeouts
await client.query(`SET LOCAL statement_timeout = '1500ms'`);Timeout evita query abandonada consumindo recursos, mas não corrige plano ruim. Combine com deadline da requisição.
Transações curtas
Não mantenha transação aberta durante chamadas HTTP ou processamento lento. Locks e snapshots permanecem ativos e podem bloquear vacuum e outras operações.
Batch
Agrupe inserts quando possível:
INSERT INTO events (id, type, payload)
VALUES ($1, $2, $3), ($4, $5, $6);Para volumes grandes, avalie COPY.
CTEs
CTEs melhoram clareza, mas seu efeito no plano depende da versão e de opções como MATERIALIZED. Confirme com EXPLAIN.
JSONB
JSONB é útil para atributos flexíveis, mas não deve substituir modelagem de campos frequentemente filtrados e relacionados. Crie índices compatíveis com operadores usados.
Pool
Mais conexões não significam mais throughput. Pools grandes aumentam concorrência no banco e podem piorar cache e I/O. Veja PgBouncer com Node.js.
Cache
Cache ajuda leituras repetidas, mas exige invalidação e proteção contra stampede. Otimize primeiro queries e índices para não mascarar problemas.
Read replicas
Relatórios e listas tolerantes a atraso podem usar réplica, sem esquecer consistência e lag. Consulte Read Replicas PostgreSQL no Node.js.
Observabilidade
Registre nome lógico da query, duração, linhas retornadas e erro. Não registre parâmetros sensíveis. Métricas devem usar nomes estáveis, não SQL completo como label.
Erros comuns
- otimizar sem medir;
- adicionar índice para toda query;
- SELECT *;
- N+1;
- OFFSET muito alto;
- transação longa;
- pool enorme;
- cache para esconder SQL ruim;
- ignorar estimativas incorretas.
Conclusão
Query Optimization no Node.js exige observar a aplicação e o PostgreSQL em conjunto. Comece pelas queries de maior impacto, leia planos, reduza round trips e limite concorrência.
Consulte a documentação de performance do PostgreSQL e a documentação de queries do node-postgres.



