Pular para o conteúdo principal

Output PostgreSQL

Aplica as mensagens em tabelas de um PostgreSQL, mantendo a tabela de destino igual à tabela de origem: inserções, atualizações e exclusões acontecem no destino conforme chegam. É o Output usado para réplica operacional — ter os dados de um sistema disponíveis em outro banco, atualizados em segundos.

Duas fases

O trabalho acontece em duas fases, automaticamente, e a virada de uma para a outra não exige nada de você:

  1. Carga inicial — o conteúdo atual das tabelas é gravado de uma vez, depois de a tabela de destino ser esvaziada.
  2. Fluxo contínuo — a partir daí, só as mudanças trafegam: inserções, atualizações e exclusões.

Pré-requisitos no PostgreSQL

  • As tabelas de destino já devem existir, com as colunas correspondentes.
  • Cada tabela precisa de índice único sobre as colunas declaradas como chave. Sem isso a atualização não tem como funcionar, e o node falha ao subir.
  • Um usuário com leitura, escrita e TRUNCATE nessas tabelas.

O que este Output precisa ler

Diferente da maioria dos Outputs, este exige um formato específico de mensagem:

ParteComo é usada
Headersop diz o que fazer; schema e table dizem de qual tabela de origem a linha veio. Os três são obrigatórios — sem eles a mensagem é recusada.
ValueA linha em JSON plano. Usado quando op é r, c ou u.
KeyAs colunas da chave em JSON. Usada quando op é d.
opO que o Output faz
rInsere a linha (carga inicial)
cInsere a linha
uAtualiza a linha correspondente à chave
dApaga a linha correspondente à chave
De onde vêm essas mensagens

O Input SQL Server CDC produz exatamente esse formato. Qualquer outro Input precisa de um Transform que monte os headers op, schema e table.

Exemplo — inserção ou atualização

Key: {"ID":42}
Value: {"ID":42,"CLIENTE":"ACME","TOTAL":249.90,"ATUALIZADO_EM":"2026-07-26T11:02:31Z"}
Headers: op=u schema=dbo table=pedidos

A linha de ID=42 na tabela de destino fica com os valores novos. Se ela não existisse, seria inserida.

Exemplo — exclusão

Key: {"ID":42}
Value: (vazio)
Headers: op=d schema=dbo table=pedidos

A linha ID=42 é apagada. Repare que o Value vem vazio — a identificação da linha está na Key.

Campos

Conexão

CampoO que éPadrão
HostEndereço do servidor PostgreSQL.
PortaPorta de conexão.5432
DatabaseBanco de destino.
UsuárioUsuário de acesso.
Senha (secret)O Secret com a senha.
SSL ModeComo a conexão é cifrada, do mais seguro para o menos: verify-full, verify-ca, require, prefer, allow, disable.require
Schema padrãoSchema usado quando a tabela de destino é informada sem schema.public

Mapeamento de tabelas

Cada tabela de origem precisa de uma linha no mapeamento apontando para a tabela de destino:

CampoO que é
Schema de origemO schema como vem no header schema da mensagem — ex.: dbo.
Tabela de origemA tabela como vem no header table — ex.: orders.
Chave primáriaColunas que identificam a linha, separadas por vírgula. São elas que o Output usa para decidir entre inserir e atualizar. As colunas precisam ter índice único no destino — isso é conferido quando o node sobe.
Tabela de destinoOnde gravar, no formato schema.tabela ou só a tabela (usando o schema padrão). Duas origens não podem apontar para o mesmo destino — cada uma tem seu próprio controle de carga inicial, e a segunda apagaria o que a primeira carregou.

Numa chave composta, o campo Chave primária recebe as colunas separadas por vírgula — ex.: PEDIDO_ID, ITEM_ID para uma mensagem cuja Key é {"PEDIDO_ID":1234,"ITEM_ID":3}.

Lote e desempenho

O Output acumula linhas antes de gravar, e o lote fecha pelo que vier primeiro:

CampoO que éPadrão
Linhas por loteQuantas linhas são acumuladas antes de uma gravação.10000
Segundos por lote (flush)Tempo máximo de espera antes de enviar um lote incompleto.10
Timeout de query (segundos)Tempo máximo de uma gravação antes de ser abortada.300
Conexões máximasQuantas conexões simultâneas com o banco.4

O lote inteiro viaja como um único parâmetro da consulta, então aumentar demais custa memória. Por isso o padrão é bem menor que o do Snowflake, onde há um custo por gravação a amortizar.

Recomeçar do zero

CampoO que é
Sufixo do Group IDA parte do marcador de leitura que você controla. O nome base é gerado a partir da pipeline e do node e não pode ser alterado. Permitido: letras, números, hífen e underline.

Trocar o sufixo e publicar de novo é o único botão de recomeçar que existe. O Output esquece até onde tinha lido, relê o tópico desde o começo, esvazia a tabela de destino e refaz a carga completa.

Apagar a tabela no braço não recomeça nada — o controle de "já carreguei esta tabela" fica do lado da plataforma, não do banco.

Cuidados de operação

Rode uma cópia só. Duas cópias no mesmo grupo de consumo podem esvaziar a tabela uma da outra durante a carga inicial.

A validação acontece na subida. O Output confere as tabelas e colunas mapeadas quando o node sobe. Um mapeamento errado falha na hora, com a mensagem do que está errado — e não silenciosamente na primeira leva de dados.

A carga inicial aguenta um node que cai no meio

A confirmação de leitura acontece depois da gravação, então um node que morre entre uma coisa e outra reenvia aquele lote ao voltar. Aqui isso não duplica nada: a inserção da carga inicial ignora linhas cuja chave já está no destino. (O Snowflake não tem essa proteção.) O preço é que uma chave repetida dentro da própria origem entra uma vez só, sem aviso.

Detalhes que evitam surpresa

  • Só as colunas que chegam são gravadas. Uma coluna que existe no destino mas não vem na mensagem é deixada em paz: o DEFAULT dela vale na inserção e o valor atual sobrevive à atualização. É o que permite manter colunas de auditoria no destino.
  • O nome da coluna é comparado sem diferenciar maiúsculas de minúsculas. Um campo ORIGEM na mensagem grava na coluna origem do destino. (O Snowflake é o oposto: lá a grafia precisa bater exatamente.)
  • Campos que o destino não tem são descartados em silêncio. Se você adiciona um campo novo num Transform, crie a coluna correspondente antes.
  • Colunas geradas nunca são escritas; colunas de identidade recebem o valor da origem, para a chave original ser preservada.