Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Partitioning PostgreSQL no Node.js: escale tabelas

Atualizado em: 23 de outubro de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

Partitioning PostgreSQL no Node.js divide uma tabela grande em partes menores administradas pelo próprio banco. A aplicação continua consultando a tabela principal, enquanto o PostgreSQL direciona leituras e escritas para partições por intervalo, lista ou hash.

Particionamento não é uma otimização automática. Ele ajuda quando consultas filtram pela mesma chave usada para particionar, quando retenção exige remover grandes blocos de dados ou quando manutenção de índices e vacuum em uma tabela única se torna difícil. Sem esse alinhamento, a complexidade pode aumentar sem ganho real.

Quando considerar particionamento

  • tabelas com centenas de milhões de linhas;
  • eventos e logs separados por data;
  • dados multi-tenant com poucos tenants muito grandes;
  • retenção por período;
  • queries quase sempre filtradas pela chave de partição;
  • índices e vacuum difíceis de administrar.

Antes de particionar, verifique índices, queries, estatísticas e modelagem. Consulte Query Optimization no Node.js.

Particionamento por intervalo

CREATE TABLE eventos (
  id bigint GENERATED ALWAYS AS IDENTITY,
  tenant_id uuid NOT NULL,
  occurred_at timestamptz NOT NULL,
  payload jsonb NOT NULL,
  PRIMARY KEY (occurred_at, id)
) PARTITION BY RANGE (occurred_at);

A chave primária inclui a coluna de particionamento. Restrições únicas globais possuem limitações; planeje IDs e unicidade conforme o modelo.

Criando partições mensais

CREATE TABLE eventos_2026_10
PARTITION OF eventos
FOR VALUES FROM ('2026-10-01') TO ('2026-11-01');

CREATE TABLE eventos_2026_11
PARTITION OF eventos
FOR VALUES FROM ('2026-11-01') TO ('2026-12-01');

Use limites em UTC ou uma convenção temporal explícita. Ambiguidade de fuso horário pode enviar registros para partições inesperadas.

Inserindo pelo Node.js

await pool.query(
  `INSERT INTO eventos (tenant_id, occurred_at, payload)
   VALUES ($1, $2, $3::jsonb)`,
  [tenantId, occurredAt, JSON.stringify(payload)]
);

A aplicação insere na tabela pai. O PostgreSQL escolhe a partição. Se não existir partição compatível, a operação falha, a menos que haja uma partição default.

Partição default

CREATE TABLE eventos_default
PARTITION OF eventos DEFAULT;

A partição default evita falhas imediatas, mas pode esconder problemas de automação. Monitore qualquer linha que caia nela e mova os dados de forma controlada.

Partition pruning

O ganho principal ocorre quando o PostgreSQL elimina partições irrelevantes.

SELECT id, payload
FROM eventos
WHERE occurred_at >= $1
  AND occurred_at < $2
  AND tenant_id = $3;

Evite envolver a chave em funções que impeçam pruning.

-- Menos favorável
WHERE date(occurred_at) = $1

-- Melhor
WHERE occurred_at >= $1
  AND occurred_at < $1 + interval '1 day'

Índices por partição

CREATE INDEX ON eventos (tenant_id, occurred_at DESC);

Ao criar um índice na tabela particionada, o PostgreSQL gerencia índices correspondentes nas partições. Verifique a versão e o comportamento operacional usado no ambiente.

Consulte Índices PostgreSQL no Node.js.

Removendo dados antigos

Uma vantagem importante é remover uma partição inteira em vez de executar um DELETE massivo.

DROP TABLE eventos_2025_01;

Também é possível destacar a partição antes de arquivar.

ALTER TABLE eventos
DETACH PARTITION eventos_2025_01;

Planeje backups, auditoria e retenção antes da remoção definitiva.

Automação de novas partições

Crie partições futuras antes do período começar. Um job diário pode verificar se existem partições para os próximos meses.

async function garantirParticoes(client, monthsAhead = 3) {
  for (let i = 0; i <= monthsAhead; i++) {
    const start = inicioDoMesUtc(i);
    const end = inicioDoMesUtc(i + 1);
    const name = `eventos_${formatarAnoMes(start)}`;

    await client.query(
      `CREATE TABLE IF NOT EXISTS ${identificadorSeguro(name)}
       PARTITION OF eventos
       FOR VALUES FROM ($1) TO ($2)`,
      [start, end]
    );
  }
}

Parâmetros não podem representar identificadores SQL. Gere nomes apenas a partir de valores controlados e use uma função de escape de identificador. Nunca aceite o nome da partição do usuário.

Locks durante manutenção

Operações DDL podem adquirir locks. Teste em ambiente semelhante à produção e use procedimentos que reduzam bloqueio. Criação de índices, attach e detach precisam de janela e observabilidade.

Particionamento por lista

Lista é útil para regiões, categorias estáveis ou grupos de tenants.

CREATE TABLE pedidos (
  tenant_group text NOT NULL,
  id uuid NOT NULL,
  created_at timestamptz NOT NULL
) PARTITION BY LIST (tenant_group);

CREATE TABLE pedidos_enterprise
PARTITION OF pedidos
FOR VALUES IN ('enterprise');

Não crie uma partição para cada tenant pequeno sem avaliar catálogos, migrations e conexões. O número excessivo de partições também possui custo.

Particionamento por hash

CREATE TABLE sessao_eventos (
  session_id uuid NOT NULL,
  occurred_at timestamptz NOT NULL,
  payload jsonb NOT NULL
) PARTITION BY HASH (session_id);

CREATE TABLE sessao_eventos_p0
PARTITION OF sessao_eventos
FOR VALUES WITH (MODULUS 4, REMAINDER 0);

Hash distribui dados, mas não simplifica retenção temporal. Escolha a estratégia de acordo com as consultas e a operação.

Subparticionamento

É possível particionar por data e depois por tenant ou hash. Isso aumenta o número de objetos e a complexidade de manutenção. Use somente quando medições justificarem.

Queries sem filtro

Uma consulta que não restringe a chave pode tocar todas as partições. Relatórios globais precisam de limites, réplicas, materialized views ou processamento assíncrono.

Paginação

Para eventos ordenados por data, use cursor composto por occurred_at e id.

SELECT id, occurred_at, payload
FROM eventos
WHERE tenant_id = $1
  AND occurred_at >= $2
  AND (occurred_at, id) < ($3, $4)
ORDER BY occurred_at DESC, id DESC
LIMIT 100;

Veja Cursor Pagination no Node.js.

Migrations

Alterar schema em tabela particionada pode afetar muitas partições. Faça mudanças compatíveis, monitore duração e valide todas as partições.

Para migrar uma tabela existente:

  1. crie a nova tabela particionada;
  2. crie partições e índices;
  3. copie dados em lotes;
  4. sincronize novas escritas;
  5. valide contagens e checksums;
  6. troque nomes ou rota de acesso;
  7. mantenha rollback preparado.

Consulte Database Migrations no Node.js.

Transações

Inserções e updates continuam transacionais. Atualizar a chave de partição pode mover a linha para outra partição e aumentar o custo. Evite chaves que mudam frequentemente.

Veja Transações PostgreSQL no Node.js.

Observabilidade

Monitore tamanho por partição, linhas, índices, vacuum, partição default, queries que varrem muitas partições e falhas por ausência de intervalo. Use EXPLAIN para confirmar pruning.

Testes

  • limites exatos entre meses;
  • timestamps em UTC;
  • inserção sem partição;
  • partição default;
  • pruning no plano;
  • remoção e arquivamento;
  • updates que mudam a chave;
  • migrations em todas as partições;
  • queries multi-tenant.

Erros comuns

  • particionar antes de otimizar queries;
  • escolher chave não usada nos filtros;
  • não criar partições futuras;
  • usar funções que impedem pruning;
  • criar partições demais;
  • supor unicidade global simples;
  • executar DDL sem avaliar locks;
  • deixar dados acumularem na default;
  • ignorar fuso horário.

Checklist

  • problema de escala medido;
  • chave alinhada às queries;
  • limites temporais explícitos;
  • partições futuras automatizadas;
  • índices definidos;
  • pruning confirmado;
  • retenção planejada;
  • DDL testado;
  • monitoramento por partição;
  • rollback disponível.

Conclusão

Partitioning PostgreSQL no Node.js ajuda a administrar tabelas muito grandes, especialmente quando dados seguem intervalos temporais e políticas de retenção. A aplicação pode continuar usando SQL normal enquanto o banco organiza os dados fisicamente.

O benefício depende da chave escolhida, do pruning e da operação contínua. Automatize partições futuras, monitore a default, teste migrations e só adote o recurso depois de confirmar que índices e queries convencionais não resolvem o problema.

Consulte a documentação oficial de particionamento do PostgreSQL e a documentação do node-postgres.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita