Como fazer carga incremental em ELT: passo a passo
As cargas incrementais são o segredo para manter um pipeline de ELT rápido e barato: em vez de recarregar milhões de registos todas as noites, processas apenas as linhas que mudaram desde a última execução. As recargas totais desperdiçam tempo e computação, e pioram à medida que os dados crescem. O padrão de watermark (marca de água) combinado com uma instrução MERGE resolve o problema de forma simples e intemporal — e funciona em SQL Server, Azure SQL, Azure Synapse ou no Warehouse do Microsoft Fabric.
Pré-requisitos
- Uma tabela de origem com uma coluna de data de modificação (por exemplo,
data_modificacao) ou um ID sempre crescente. - Um destino SQL onde transformar os dados (SQL Server, Azure SQL, Synapse ou Fabric Warehouse).
- Permissões para criar tabelas e executar
INSERT,MERGEeUPDATE. - Noções básicas de SQL e, mais tarde, uma ferramenta de orquestração para agendar.
Passo 1: Criar a tabela de controlo (watermark)
O watermark é apenas o valor mais alto já processado — normalmente uma data/hora. Guardamo-lo numa pequena tabela de controlo, para que cada execução saiba exatamente onde a anterior parou. Cria a tabela uma única vez e regista um valor inicial baixo, para que a primeira carga traga o histórico completo:

CREATE TABLE dbo.controlo_carga (
tabela_origem VARCHAR(128) NOT NULL PRIMARY KEY,
ultimo_watermark DATETIME2 NOT NULL
);
-- Valor inicial baixo para a 1a carga trazer todo o historico
INSERT INTO dbo.controlo_carga (tabela_origem, ultimo_watermark)
VALUES ('vendas', '1900-01-01');
Passo 2: Ler o watermark atual
No início de cada execução, lê o valor guardado. Este passa a ser o limite inferior da tua janela de dados: só queremos linhas mais recentes do que ele. Guarda-o numa variável para o reutilizar nos passos seguintes.
DECLARE @watermark DATETIME2;
SELECT @watermark = ultimo_watermark
FROM dbo.controlo_carga
WHERE tabela_origem = 'vendas';
Passo 3: Extrair e carregar (E + L) as linhas novas
Em ELT, primeiro trazemos os dados em bruto para uma área de staging e só depois os transformamos — é isto que distingue ELT de ETL. Extrai apenas as linhas alteradas desde o watermark e carrega-as numa tabela de staging. Assim reduzes drasticamente o volume transferido e a carga fica rápida, mesmo em tabelas com milhões de registos.
-- Limpa a staging da execucao anterior
TRUNCATE TABLE stg.vendas;
-- Carrega so o que mudou desde o watermark
INSERT INTO stg.vendas (id_venda, cliente, total, data_modificacao)
SELECT id_venda, cliente, total, data_modificacao
FROM origem.vendas
WHERE data_modificacao > @watermark;
Escolhe uma coluna de watermark fiável: deve aumentar sempre que uma linha é criada ou alterada. Uma data_modificacao atualizada pela aplicação ou por um trigger é ideal.
Passo 4: Transformar com MERGE (upsert)
Agora aplicamos a transformação dentro do destino, aproveitando a sua capacidade de computação. O MERGE faz upsert: atualiza as linhas que já existem e insere as novas, tudo numa só instrução e numa só passagem pelos dados. É o coração de uma carga incremental e evita duplicados.
MERGE INTO dw.vendas AS destino
USING stg.vendas AS origem
ON destino.id_venda = origem.id_venda
WHEN MATCHED THEN
UPDATE SET destino.cliente = origem.cliente,
destino.total = origem.total,
destino.data_modificacao = origem.data_modificacao
WHEN NOT MATCHED BY TARGET THEN
INSERT (id_venda, cliente, total, data_modificacao)
VALUES (origem.id_venda, origem.cliente, origem.total, origem.data_modificacao);
Passo 5: Atualizar o watermark
Para a próxima execução começar exatamente onde esta terminou, guarda o valor máximo de data_modificacao que acabaste de processar. Usa a staging como fonte e protege-te contra execuções vazias, para nunca ultrapassares dados que ainda não carregaste.
UPDATE c
SET c.ultimo_watermark = (SELECT MAX(data_modificacao) FROM stg.vendas)
FROM dbo.controlo_carga AS c
WHERE c.tabela_origem = 'vendas'
AND EXISTS (SELECT 1 FROM stg.vendas);
Verificar o resultado
Confirma que a carga funcionou com três verificações simples:
- Compara as contagens:
SELECT COUNT(*) FROM dw.vendas;deve refletir os registos esperados. - Consulta a tabela de controlo e confirma que
ultimo_watermarkavançou para a data mais recente. - Executa o pipeline uma segunda vez sem alterar dados na origem: a staging deve ficar vazia e o
MERGEnão deve alterar nenhuma linha. É a prova de que a carga é mesmo incremental e idempotente.
Conclusão
Com uma tabela de controlo, um filtro por watermark e um MERGE, transformaste uma carga total pesada numa carga incremental leve e repetível. A partir daqui, agenda o processo (por exemplo, com Azure Data Factory ou um pipeline do Microsoft Fabric), acrescenta logs para saber quantas linhas foram processadas em cada execução e trata as eliminações na origem com uma coluna de soft delete. Qual será a primeira tabela do teu modelo que vais migrar para cargas incrementais?