Índices PostgreSQL no Node.js aceleram consultas ao manter estruturas adicionais que ajudam o banco a localizar linhas sem percorrer toda a tabela. O benefício vem com custo de armazenamento e escrita, por isso cada índice deve responder a uma necessidade observada.
Índice B-tree
CREATE INDEX idx_orders_created_at
ON orders (created_at DESC);B-tree atende igualdade, intervalos e ordenação em muitos casos.
Índice composto
CREATE INDEX idx_orders_tenant_status_created
ON orders (tenant_id, status, created_at DESC);A ordem importa. Coloque primeiro colunas usadas em igualdade e depois filtros de intervalo ou ordenação, conforme as consultas reais.
Consulta no Node.js
const result = await pool.query(
`SELECT id, total, created_at
FROM orders
WHERE tenant_id = $1 AND status = $2
ORDER BY created_at DESC
LIMIT 50`,
[tenantId, status]
);Use parâmetros para segurança e estabilidade do plano.
EXPLAIN ANALYZE
EXPLAIN (ANALYZE, BUFFERS)
SELECT ...;O comando executa a query. Use com cuidado em produção, especialmente em escritas ou consultas pesadas.
Seq Scan não é sempre ruim
Em tabelas pequenas ou quando grande parte das linhas será lida, varredura sequencial pode ser mais eficiente. Não force índice sem entender o plano.
Índice parcial
CREATE INDEX idx_jobs_pending
ON jobs (created_at)
WHERE status = 'pending';Índices parciais reduzem tamanho quando a aplicação consulta frequentemente um subconjunto previsível.
Índice de expressão
CREATE INDEX idx_users_lower_email
ON users (lower(email));A query precisa usar expressão compatível.
INCLUDE
CREATE INDEX idx_orders_lookup
ON orders (tenant_id, created_at DESC)
INCLUDE (status, total);Colunas incluídas podem permitir index-only scan, dependendo da visibilidade das páginas.
GIN e JSONB
GIN é útil para arrays, full-text e JSONB, mas custa mais em escrita. Indexe operadores realmente usados.
Índices e ORDER BY
Um índice que combina filtros e ordenação evita sort caro e funciona bem com paginação por cursor.
Índices únicos
CREATE UNIQUE INDEX uq_users_tenant_email
ON users (tenant_id, lower(email));Além de desempenho, o índice garante invariante contra concorrência.
Criação concorrente
CREATE INDEX CONCURRENTLY idx_name ON table_name (...);Reduz bloqueio de escrita, mas não pode executar dentro de transação comum e exige tratamento de falhas. Consulte Database Migrations no Node.js.
Índices não usados
Revise estatísticas antes de remover. Um índice pode ser necessário apenas em fechamento mensal ou incidente específico.
Bloat e manutenção
Atualizações e deletes podem gerar bloat. Acompanhe vacuum, tamanho e saúde dos índices. Não rode rebuild sem avaliar bloqueios e espaço.
Observabilidade
Use pg_stat_statements para localizar consultas caras e pg_stat_user_indexes para uso. Relacione planos a latência observada na aplicação.
Erros comuns
- indexar toda coluna;
- ordem inadequada no composto;
- não medir escrita;
- ignorar índices duplicados;
- usar função diferente da expressão indexada;
- criar índice bloqueante em tabela grande;
- otimizar query inexistente.
Conclusão
Índices PostgreSQL no Node.js devem ser projetados a partir de consultas reais, planos e SLOs. Combine filtros, ordenação e restrições, medindo também custo de escrita.
Consulte a documentação de índices do PostgreSQL e a documentação de EXPLAIN.




