Skip to content

Tipos de Carga

Todo fluxo que grava no Data Warehouse tem um tipo de carga (load_type). Ele responde a uma única pergunta: a cada execução, o que o fluxo apaga antes de inserir os dados novos?

São três valores, e não existem outros:

TipoO que apaga antes de inserirColuna de controle
TotalTudo. A tabela é esvaziada e recarregadaNão usa
TemporalSó as linhas dentro de uma janela de datasColuna de data (partição)
IncrementalNada. Só insere ou atualizaColuna de rastreio (ex.: updated_at)

O tipo de carga é uma propriedade do fluxo, não da tabela. Quem executa a regra é o nó InsertDatawarehouse: ele monta o DELETE conforme o tipo e depois insere o resultado do fluxo.

IMPORTANT

A escolha errada aqui não quebra a execução: ela duplica ou perde linhas em silêncio, e o erro só aparece semanas depois num total que não fecha. Vale gastar tempo nesta decisão.


🔄 Total (recarga completa)

Esvazia a tabela e recarrega tudo, a cada execução.

  • Condição de DELETE: 1=1, ou seja, apaga todas as linhas.
  • Exige: nada. Nenhuma coluna de controle.
  • Quando usar: tabelas pequenas, tipicamente dimensões e tabelas de referência (cidades, categorias, plano de contas), ou qualquer origem que simplesmente não tenha como ser rastreada de forma incremental.

É o tipo mais simples e o único que não tem risco de duplicar registros: o estado final depende só da última execução. O custo é reprocessar a origem inteira toda vez, o que fica inviável em tabelas fato grandes.


📅 Temporal (recarga por janela de datas)

Recarrega apenas um intervalo de datas, delimitado por uma coluna de data da tabela.

  • Condição de DELETE: TRUNC("COLUNA") BETWEEN 'StartDate' AND 'EndDate'.
  • Exige: load_type_column no fluxo apontando para a coluna de data, e a mesma coluna definida como partition_column na tabela do DW.
  • Variáveis injetadas: {StartDate} e {EndDate}, disponíveis nos nós de extração. Os nós precisam usá-las, senão o fluxo traz a base inteira e a janela não filtra nada na origem.
sql
SELECT * FROM vendas
WHERE DATA_EMISSAO BETWEEN '{StartDate}' AND '{EndDate}'

Este é o tipo padrão para tabelas fato grandes: roda todo dia recarregando os últimos N dias, o que absorve correções retroativas na origem sem reprocessar o histórico.

WARNING

A coluna de partição precisa ser imutável. Use data_emissao, data_venda, created_at. Nunca data_vencimento ou qualquer data que possa ser alterada depois. Se o valor mudar, o DELETE limpa a janela antiga, o INSERT grava o registro na janela nova, e a linha antiga permanece em outra janela que ninguém mais vai apagar. Resultado: duplicata. Para datas mutáveis, use Incremental com chave única.


➕ Incremental (append ou upsert)

Não apaga nada. Insere só o que é novo desde a última execução.

  • Condição de DELETE: nenhuma.
  • Exige: load_type_column no fluxo apontando para a coluna de rastreio (updated_at, created_at ou um ID sequencial).
  • Variável injetada: {LastDataPoint}, o maior valor da coluna de rastreio visto na execução anterior.
  • Primeira execução: carrega tudo, porque ainda não existe LastDataPoint.
sql
SELECT * FROM pedidos
WHERE UPDATED_AT > '{LastDataPoint}'

O que acontece com um registro que já existe na tabela depende do key_type da tabela de destino:

  • key_type: unique com key_columns preenchido: o Doris faz upsert. Linhas com a mesma chave são substituídas, a última carga vence.
  • key_type: duplicate: append puro. A linha nova é acrescentada e a antiga fica lá.

Ou seja, rastrear por updated_at sem key_type: unique produz uma cópia do pedido a cada alteração dele. Rastreando por created_at num log append-only, duplicate é o correto.


🔗 O lado da tabela

O tipo de carga é do fluxo, mas quem cumpre metade do contrato é a tabela do DW. Três propriedades importam:

Propriedade da tabelaPara que serve
key_typeunique deduplica linhas com a mesma key_columns (upsert). duplicate acumula.
key_columnsAs colunas que formam a chave. Só faz sentido com key_type: unique.
partition_columnA coluna de data usada pelo DELETE da carga Temporal. Só uma por tabela.

As três são estruturais: mudar qualquer uma força um DROP e CREATE da tabela física no Doris e as linhas são perdidas. Detalhes e restrições em Referência: table.


🧭 Escolhendo o tipo

CenárioTipoColuna de controlekey_type
Tabela de referência pequena (dimensão, cadastro)Total(nenhuma)duplicate
Fato grande com data imutável (vendas, faturamento)Temporaldata_emissao (Date)unique
Log ou evento append-onlyIncrementalcreated_atduplicate
Registro mutável (pedido, chamado, contas a receber)Incrementalupdated_atunique + key_columns

TIP

Numa carga Temporal que recarrega uma janela, prefira key_type: unique. Se o DELETE da janela falhar por qualquer motivo, duplicate multiplica os registros; unique os deduplica pela chave.


📄 Exemplo: fato de vendas com carga Temporal

Um fluxo que recarrega diariamente os últimos dias de vendas, particionado pela data de emissão do pedido.

O fluxo declara o tipo de carga e a coluna de partição:

yaml
# flows/carga-vendas--42866.yaml
# yaml-language-server: $schema=https://docs.horusbi.com.br/schemas/v2/flow.schema.json
id: 42866
kind: flow
lumo: v2
tenantId: 853
---
nome: Carga Vendas
load_type: Temporal
load_type_column: DATA_EMISSAO   # obrigatório em Temporal e Incremental

nodes:
  Processors:
    - internalId: ext_vendas
      kind: ExtractPostgreSQL
      inputs: []
      options:
        Credential: erp-producao
        # {StartDate} e {EndDate} são injetadas pelo tipo de carga Temporal.
        SQL: |
          SELECT
            p.id            AS PEDIDO_ID,
            i.produto_id    AS PRODUTO_ID,
            p.data_emissao  AS DATA_EMISSAO,
            i.valor_item    AS VALOR_ITEM
          FROM public.pedidos p
          JOIN public.pedido_itens i ON i.pedido_id = p.id
          WHERE p.data_emissao >= '{StartDate}'
            AND p.data_emissao <= '{EndDate}'

    - internalId: load_dw
      kind: InsertDatawarehouse
      inputs: [ext_vendas]
      options:
        TableID: 44940
        Mode: Datawarehouse

  Connections:
    - from: ext_vendas
      to: load_dw

E a tabela de destino declara a partição e a chave:

yaml
# tables/fato-vendas--44940.yaml
# yaml-language-server: $schema=https://docs.horusbi.com.br/schemas/v2/table.schema.json
id: 44940
kind: table
lumo: v2
tenantId: 853
---
nome: fato_vendas
table_type: table

key_type: unique
key_columns: [PEDIDO_ID, PRODUTO_ID]
partition_column: DATA_EMISSAO   # a mesma coluna do load_type_column do flow

A cada execução, o InsertDatawarehouse apaga as linhas de fato_vendas cuja DATA_EMISSAO cai na janela pedida e insere as que o fluxo trouxe. Fora da janela, o histórico não é tocado.


▶️ Escolhendo a janela na execução

O load_type define a regra; a janela concreta é escolhida na hora de executar. Na execução manual, o Horus mostra o seletor de modo (Total, Temporal com Dias Passados / Mês e Ano / Ano, ou Incremental). Pela CLI, o mesmo controle está em --context:

bash
lumo flow run flow:42866 --context Temporal --wait   # recarrega a janela temporal
lumo flow run flow:42866 --context Total --wait      # recarga completa pontual

Dá para forçar uma carga Total pontual num fluxo Temporal, tipicamente para a carga histórica inicial ou para um reprocessamento. Veja Execução e Agendamento.


📚 Relacionados