(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa
ETL

Carga incremental em ETL: carregar apenas dados novos

João Barros 04 de July de 2026 4 min de leitura

Recarregar a tabela inteira a cada execução funciona bem quando há poucos dados, mas torna-se lento e caro à medida que a origem cresce — e obriga a reprocessar milhões de linhas que não mudaram. A carga incremental num ETL resolve exatamente isto: processa apenas os registos novos ou alterados desde a última execução, poupando tempo, computação e dinheiro. O padrão mais simples e fiável para o conseguir usa uma coluna de watermark (marca de água), e é esse que vais montar a seguir, passo a passo.

Pré-requisitos

  • Uma tabela de origem com uma coluna que cresce sempre — uma data/hora de modificação (por exemplo data_modificacao) ou um ID incremental.
  • Uma tabela de destino no teu data warehouse (SQL Server, PostgreSQL ou outro).
  • Permissão para criar uma pequena tabela de controlo.
  • Noções básicas de SQL (INSERT, UPDATE, MERGE).

Passo 1: Escolher a coluna de watermark

A watermark é a coluna que te diz até onde já carregaste. Para funcionar sem falhas, tem de crescer sempre e nunca ser reutilizada nem alterada para trás. As duas escolhas mais comuns são uma coluna de data/hora de modificação (como data_modificacao) ou um identificador incremental gerado pela base de dados. Uma boa watermark evita dois problemas clássicos: saltar registos (gaps) e voltar a carregar linhas já processadas (duplicados). No exemplo, a origem é a tabela vendas(id, cliente, total, data_modificacao) e a watermark é data_modificacao.

Carga incremental em ETL: carregar apenas dados novos

Passo 2: Criar a tabela de controlo

Precisas de guardar, entre execuções, o último valor já processado. Uma pequena tabela de controlo chega para isso. Na primeira vez, inicia-a com uma data antiga, para que a carga inicial traga todos os registos.

CREATE TABLE etl_control (
    tabela          VARCHAR(100) PRIMARY KEY,
    last_watermark  DATETIME2 NOT NULL
);

INSERT INTO etl_control (tabela, last_watermark)
VALUES ('vendas', '1900-01-01');

Passo 3: Ler a watermark e capturar a nova

No início de cada execução, lê o último valor processado e guarda também o valor máximo atual da origem. Capturar o máximo antes de carregar evita perder registos que entrem durante o processo.

DECLARE @last_watermark DATETIME2 =
    (SELECT last_watermark FROM etl_control WHERE tabela = 'vendas');

DECLARE @new_watermark DATETIME2 =
    (SELECT MAX(data_modificacao) FROM vendas);

Passo 4: Carregar apenas os dados novos com MERGE

Agora seleciona só as linhas cuja data_modificacao é maior que a última watermark e aplica-as ao destino. O MERGE faz um upsert numa única instrução: atualiza as linhas que já existem e insere as que são novas, comparando pela chave. Fazer tudo num só comando é mais eficiente e mantém a lógica mais clara do que separar em UPDATE e INSERT manuais.

MERGE INTO dw_vendas AS destino
USING (
    SELECT id, cliente, total, data_modificacao
    FROM vendas
    WHERE data_modificacao > @last_watermark
) AS origem
ON destino.id = origem.id
WHEN MATCHED THEN
    UPDATE SET destino.cliente = origem.cliente,
               destino.total   = origem.total,
               destino.data_modificacao = origem.data_modificacao
WHEN NOT MATCHED THEN
    INSERT (id, cliente, total, data_modificacao)
    VALUES (origem.id, origem.cliente, origem.total, origem.data_modificacao);
Dica: usa sempre > (maior que) e não >= na comparação da watermark, para não reprocessar a última linha já carregada.

Passo 5: Atualizar a watermark

Depois de a carga terminar com sucesso, grava o novo valor na tabela de controlo. Na próxima execução, só os registos mais recentes do que este momento serão processados.

UPDATE etl_control
SET last_watermark = @new_watermark
WHERE tabela = 'vendas';

Verificar o resultado

A melhor forma de confirmar que a carga incremental funciona é correr o pipeline duas vezes seguidas. Na primeira, ele traz todos os registos; na segunda, sem dados novos na origem, deve processar zero linhas. Para testar a fundo, altera ou insere um único registo na origem e volta a correr: apenas essa linha deve chegar ao destino. Podes confirmar a contagem com uma consulta simples:

SELECT COUNT(id) AS total_destino FROM dw_vendas;

Se o número aumentar exatamente o esperado a cada execução, o padrão está a funcionar como deve.

Conclusão

Com uma coluna de watermark, uma tabela de controlo e um MERGE, transformaste uma carga total pesada numa carga incremental rápida e barata. A partir daqui, podes envolver os passos numa transação para garantir consistência, registar o número de linhas processadas para auditoria, e tratar as eliminações na origem com uma marca de soft delete ou com Change Data Capture (CDC). Que coluna da tua origem vais usar como watermark — uma data de modificação ou um ID incremental?

Partilhar: