Carga incremental em ETL: carregar apenas dados novos
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.

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?