Escolha explicitamente a semântica da tabela.
Um modo de gravação não é apenas um detalhe de implementação. Ele define como os novos dados se relacionam com o estado de destino existente, como o histórico é preservado e qual integridade de origem é necessária.
Nomes de modo público
Use estes nomes em contratos:
| Modo | Display name | Significado |
|---|---|---|
append | Append | Adicione linhas preparadas sem reconciliar as linhas de destino existentes. |
overwrite | Overwrite | Substitua o alvo completo ou o escopo do alvo declarado. |
upsert | Upsert do estado atual | Mantenha uma linha atual por chave mesclando as linhas de origem com as de destino. |
hash_diff_upsert | Hash-diff upsert | Atualize apenas as linhas cujo conteúdo comparado foi alterado. |
historical | Historical | Preservar versões antigas e atuais com janelas de validade. |
snapshot_reconcile_soft_delete | Reconciliação de instantâneo com exclusão reversível | Reconcilie um instantâneo completo e marque as chaves ativas ausentes como inativas/excluídas. |
Decision guide
| Need | Modo recomendado | Design note |
|---|---|---|
| Capture everything as received | append | Mantenha o Bronze simples e auditável. |
| Rebuild a small aggregate | overwrite | Use quando a recomputação completa for mais barata que a lógica incremental. |
| Keep one row per key | upsert | Valide chaves nulas e duplicadas antes de MERGE. |
| Rastreie as mudanças no estado atual de forma barata | hash_diff_upsert | Precisa de pedido de desduplicação estável para o estado mais recente. |
| Audit historical versions | historical | Restrict change columns to meaningful business attributes. |
| Desativar registros ausentes da fonte | snapshot_reconcile_soft_delete | Não combine com marca d'água ou filtros parciais. |
Requisitos do modo
A tabela abaixo é a lista de verificação prática do contrato. Se um campo estiver listado como obrigatório, a validação deverá falhar antes que a estrutura execute uma gravação perigosa ou ambígua.
| Modo | Campos obrigatórios | Regras de qualidade recomendadas | Não use quando |
|---|---|---|---|
append | Nenhum além da origem e do destino. | required_columns, not_null para chaves comerciais, expressões opcionais. | O mesmo lote pode ser reproduzido sem uma chave de idempotência. |
overwrite | Nenhum além da origem e do destino. | min_rows e colunas obrigatórias para evitar a substituição de uma tabela por uma origem vazia ou malformada. | A fonte é parcial ou não determinística. |
upsert | merge_keys. | not_null e unique_key em chaves de mesclagem; desduplicar com ordem determinística. | Várias linhas de origem podem atualizar a mesma chave de destino. |
hash_diff_upsert | merge_keys mais hash_keys ou hash_strategy: all_columns_except; ordem determinística do estado mais recente quando a história existe. | not_null, unique_key após desduplicação, valores aceitos para dimensões de baixa cardinalidade. | O destino possui diversas versões por chave e nenhuma coluna de ordenação confiável. |
historical | merge_keys ou chaves específicas de modo, além de alterar colunas quando a comparação de negócios deve ter escopo definido. | Chaves obrigatórias, exclusividade após eliminação de duplicação, data de vigência não nula quando usada. | Você só precisa do estado atual ou a fonte não poderá produzir chaves de negócios estáveis. |
snapshot_reconcile_soft_delete | merge_keys e evidência de integridade da fonte. | not_null, unique_key, min_rows para instantâneos completos. | A fonte é filtrada, incremental, com marca d’água ou representa apenas uma fatia do estado atual. |
Otimização e layout da tabela
A semântica de escrita e o layout físico são escolhas separadas. Mantenha o modo focado no estado do negócio e use configurações de layout para melhorar o desempenho da consulta ou o comportamento de manutenção.
| Field | Usar | Guidance |
|---|---|---|
partition_column, partition_value | Scope overwrite/replace patterns to a physical partition. | Use partition_value apenas com partition_column. Não confunda filtragem de partição com integridade de origem. |
merge_strategy | Selecione a estratégia MERGE usada pelos modos de mesclagem. | Use o padrão, a menos que o destino seja particionado e o contrato declare explicitamente a estratégia de partição. |
merge_partition_column | Chave de partição para estratégias de mesclagem com reconhecimento de partição. | Necessário para estratégias de mesclagem de partição. |
replace_partitions_source_complete | Declara que a origem contém a fatia de partição completa que está sendo substituída. | Use para substituição de partição somente quando a origem realmente cobrir toda a partição afetada. |
cluster_columns | Colunas de clustering líquido para tabelas Databricks. | Prefira novas tabelas Delta gerenciadas por Databricks quando os padrões de consulta forem conhecidos. |
zorder_columns | Colunas para ZORDER explícito após gravação. | Use com optimize_after_write=true; não declare isso como uma dica passiva. |
delta_properties | Propriedades da tabela Delta no momento da criação/atualização. | Use para CDF, retenção, otimização automática e comportamento em nível de tabela que pertence ao contrato de destino. |
Partition replacement
upsert com merge_strategy: replace_partitions é para instantâneos completos de partições. ContractForge usa Databricks SQL INSERT INTO... REPLACE WHERE... SELECT para que as linhas correspondentes ao predicado da partição sejam substituídas pela consulta recebida como uma operação Delta.
Use isto somente quando a fonte cobrir toda a partição afetada:
mode: upsert
merge_strategy: replace_partitions
merge_partition_column: order_date
replace_partitions_source_complete: true
merge_keys: [order_id]
Se a origem for incremental, atrasada ou filtrada, use delta ou delta_by_partition.
Reconciliação de instantâneo com exclusão reversível
Este modo é intencionalmente defensivo. A origem deve representar o estado atual completo, caso contrário, a estrutura não poderá dizer se uma linha de destino desapareceu ou simplesmente estava fora da fatia carregada.
- YAML
mode: snapshot_reconcile_soft_delete
merge_keys: [device_id]
source:
type: connector
connector: table
table: main.raw.devices_snapshot
read:
source_complete: true
Operational note
Use modos incrementais para fontes parciais. Um instantâneo com marca d'água é uma contradição e deve falhar antes que os dados sejam tocados.
Merge safety
Os modos baseados em MERGE falham antes da gravação quando a origem contém chaves nulas ou duplicadas que tornariam a atualização de destino ambígua. O guardrail é genérico e protege todos os alvos de mesclagem contra atualizações não determinísticas.
mode: upsert
merge_keys: [customer_id]
quality_rules:
not_null: [customer_id]
unique_key: [customer_id]
transform:
deduplicate:
keys: [customer_id]
order_by: updated_at DESC NULLS LAST
Métricas por modo
Cada modo retorna métricas lógicas mesmo quando o histórico do Delta não expõe os mesmos contadores de operação em tempos de execução. Use metrics_source para entender se os valores vieram de cálculos lógicos, métricas de operação Delta ou uma combinação.
| Modo | Important metrics | Dashboard interpretation |
|---|---|---|
append | rows_inserted, rows_written | Tamanho do lote e rendimento de ingestão. |
upsert | rows_inserted, rows_updated | Proporção de alteração nas tabelas do estado atual. |
hash_diff_upsert | rows_written, contagens de alteração de hash quando disponível, hash_diff_candidate_rows em AWS | Se os lotes de origem estão realmente mudando o estado de destino. No Iceberg, os contadores de reescrita de arquivos podem ser maiores que a contagem de alterações comerciais. |
historical | versões expiradas e versões inseridas | Agitação histórica e comportamento de dimensão em mudança lenta. |
snapshot_reconcile_soft_delete | linhas inseridas, atualizadas e excluídas de forma reversível | Monitoramento de integralidade e desaparecimento inesperado. |
Exemplos de modo
- YAML
- Python
# Current-state table
source:
type: connector
connector: jdbc
options:
url: "{{ secret:crm/jdbc_url }}"
dbtable: public.customers
driver: org.postgresql.Driver
target:
catalog: main
schema: crm_curated
table: s_customers
layer: silver
mode: upsert
merge_keys: [customer_id]
transform:
deduplicate:
keys: [customer_id]
order_by: updated_at DESC NULLS LAST
quality_rules:
not_null: [customer_id]
unique_key: [customer_id]
from contractforge import ingest
result = ingest(
source={
"type": "connector",
"connector": "jdbc",
"options": {
"url": "{{ secret:crm/jdbc_url }}",
"dbtable": "public.customers",
"driver": "org.postgresql.Driver",
},
},
target_catalog="main",
target_schema="crm_curated",
target_table="s_customers",
layer="silver",
mode="upsert",
merge_keys=["customer_id"],
transform={
"deduplicate": {
"keys": ["customer_id"],
"order_by": "updated_at DESC NULLS LAST",
},
},
quality_rules={
"not_null": ["customer_id"],
"unique_key": ["customer_id"],
},
)
Comportamento de aumento em caso de falha
As gravações com falha não são cargas silenciosas por padrão. O API grava a evidência de execução e, em seguida, aumenta o ContractForgeExecutionError, portanto, os trabalhos e notebooks do Databricks falham naturalmente.
from contractforge import ContractForgeExecutionError, ingest
try:
result = ingest(...)
except ContractForgeExecutionError as exc:
display(exc.result)
raise