Snapshots, Seeds e Sources Avançadas
Domine snapshots dbt para Dimensões de Mudança Lenta no Redshift usando a nova especificação YAML (dbt 1.9+), configure seeds para dados de referência e projete configurações de fonte de nível profissional com verificações de frescor e integração Redshift Spectrum.
Snapshots, Seeds e Sources Avançadas
Três tipos de recursos do dbt são frequentemente subutilizados em projetos avançados: snapshots para rastrear mudanças históricas, seeds para pequenos conjuntos de dados de referência e sources para declarações de dados brutos. No Redshift, cada um tem considerações específicas de performance e novos recursos introduzidos no dbt-core 1.9.
Entender esses três recursos é essencial porque:
- Snapshots resolvem o problema de rastrear mudanças em dados de referência ao longo do tempo
- Seeds fornecem uma maneira simples de gerenciar dados de referência pequenos e estáveis
- Sources formalizam a relação entre seus modelos e os dados brutos externos
Snapshots: Rastreando Dimensões de Mudança Lenta
Snapshots implementam Dimensões de Mudança Lenta Tipo 2 (SCD2) — eles rastreiam como uma linha muda ao longo do tempo mantendo todas as versões históricas com timestamps de validade.
A Nova Especificação YAML de Snapshot (dbt-core 1.9+)
Antes do dbt 1.9, snapshots só podiam ser definidos em arquivos .sql com um bloco {% snapshot %}. Agora podem ser declarados inteiramente em YAML:
# snapshots/schema.yml (especificação YAML dbt 1.9+)
snapshots:
- name: snap_customers
description: "Snapshot SCD2 da dimensão de clientes"
relation: source('crm', 'customers') # fonte a ser snapshotada
config:
# Estratégia: check — detecta mudanças comparando hash das colunas especificadas
strategy: check
unique_key: customer_id
check_cols:
- email
- phone
- customer_segment
- billing_address
- shipping_address
# Configurações de performance Redshift
target_schema: snapshots
target_database: analytics
# Nomes customizados de colunas de metadados (dbt 1.9+)
snapshot_meta_column_names:
dbt_scd_id: _scd_id
dbt_updated_at: _updated_at
dbt_valid_from: _valid_from
dbt_valid_to: _valid_to
# Lidar com hard deletes — marcar registros como deletados quando desaparecem
invalidate_hard_deletes: true
# Específico Redshift
dist: customer_id
sort: [_valid_from, _valid_to]
sort_type: compound
backup: trueEstratégia Baseada em Timestamp
snapshots:
- name: snap_orders
relation: source('oms', 'orders')
config:
strategy: timestamp
unique_key: order_id
updated_at: updated_at # coluna que rastreia a última modificação
target_schema: snapshots
snapshot_meta_column_names:
dbt_scd_id: _scd_id
dbt_updated_at: _updated_at
dbt_valid_from: _valid_from
dbt_valid_to: _valid_to
# Indicador customizado para registros "atuais" (dbt 1.9+)
# Padrão é NULL; defina uma data futura para compatibilidade com ferramentas BI
dbt_valid_to_current: '9999-12-31'
dist: order_id
sort: [_valid_from]
sort_type: compoundCom dbt_valid_to_current: '9999-12-31', registros atuais mostram _valid_to = '9999-12-31' em vez de NULL, o que é muito mais amigável para ferramentas de BI como Tableau ou QuickSight em filtros de data.
Snapshot Baseado em SQL (ainda suportado)
-- snapshots/snap_products.sql
{% snapshot snap_products %}
{{ config(
target_schema='snapshots',
strategy='check',
unique_key='product_id',
check_cols=['product_name', 'price', 'category', 'is_active'],
invalidate_hard_deletes=true,
snapshot_meta_column_names={
'dbt_scd_id': '_scd_id',
'dbt_updated_at': '_updated_at',
'dbt_valid_from': '_valid_from',
'dbt_valid_to': '_valid_to'
},
dbt_valid_to_current='9999-12-31',
dist='product_id',
sort=['_valid_from'],
sort_type='compound'
) }}
select
product_id,
product_name,
price,
category,
subcategory,
is_active,
supplier_id
from {{ source('catalog', 'products') }}
{% endsnapshot %}Executando Snapshots
# Executar todos os snapshots
dbt snapshot
# Executar um snapshot específico
dbt snapshot --select snap_customers
# Snapshot + modelos downstream em um comando
dbt build --select snap_customers+Consultando Snapshots
-- Estado atual apenas
select *
from analytics.snapshots.snap_customers
where _valid_to = '9999-12-31';
-- Estado histórico em um ponto no tempo
select *
from analytics.snapshots.snap_customers
where _valid_from <= '2024-06-01'
and (_valid_to > '2024-06-01' or _valid_to = '9999-12-31');
-- Histórico completo de mudanças para um cliente
select *
from analytics.snapshots.snap_customers
where customer_id = 42
order by _valid_from;Seeds: Gerenciamento de Dados de Referência
Seeds são arquivos CSV armazenados em seu projeto dbt que são carregados no warehouse com dbt seed. São ideais para pequenas tabelas de referência que mudam lentamente.
Configurando Seeds para Redshift
# dbt_project.yml
seeds:
my_analytics:
# Configurações padrão para todos os seeds
+schema: reference
+backup: false
# Configurações específicas de seed
country_codes:
+column_types:
iso_code: varchar(2)
iso3_code: varchar(3)
country_name: varchar(100)
region: varchar(50)
+dist: all # tabela de consulta pequena — copiar para todos os nós
+sort: iso_code
status_mapping:
+column_types:
raw_status: varchar(10)
display_status: varchar(50)
is_terminal: boolean
+dist: allArquivos Seed
seeds/
├── country_codes.csv
├── status_mapping.csv
└── region_hierarchy.csv
# seeds/status_mapping.csv
raw_status,display_status,is_terminal
P,Pending,false
S,Shipped,false
D,Delivered,true
C,Cancelled,true
RJ,Rejected,true
RF,Refunded,trueCarregando Seeds
# Carregar todos os seeds
dbt seed
# Carregar e mostrar contagens de linhas
dbt seed --show
# Carregar apenas seeds modificados (usa comparação de hash de arquivo)
dbt seed --select status_mapping
# Full refresh de um seed (truncate + reload)
dbt seed --full-refresh --select status_mappingQuando Usar Seeds vs. Tabelas Fonte
| Situação | Use |
|---|---|
| Tabela de consulta pequena (< 1.000 linhas), muda raramente | Seed |
| Dados de referência pertencentes a outra equipe | Source |
| Códigos de país, mapeamentos de status, calendários fiscais | Seed |
| Dados mestre de clientes do CRM | Source |
| Dados que mudam mais de uma vez por semana | Source com snapshot |
Configuração Avançada de Sources
Sources declaram tabelas externas (dados brutos) sobre as quais os modelos dbt são construídos. A configuração avançada de sources adiciona verificações de frescor, quoting e suporte a Redshift Spectrum.
Configuração de Source de Produção
# models/staging/sources.yml
version: 2
sources:
- name: raw_events
description: "Eventos de clickstream brutos do Kinesis Firehose -> S3 -> Redshift COPY"
database: analytics
schema: raw
# Frescor no nível da fonte: avisar se qualquer tabela nesta fonte estiver desatualizada
freshness:
warn_after: {count: 1, period: hour}
error_after: {count: 6, period: hour}
# Quoting de colunas (Redshift é case-insensitive mas pode precisar de quoting para palavras reservadas)
quoting:
database: false
schema: false
identifier: false
tables:
- name: events
description: "Eventos brutos de page view e click"
identifier: raw_events_partitioned # nome real da tabela se diferente de 'events'
# Override de frescor no nível da tabela
freshness:
warn_after: {count: 30, period: minute}
error_after: {count: 2, period: hour}
filter: "event_date >= current_date - 2" # verificar apenas partições recentes
# Qual coluna determina o frescor
loaded_at_field: event_timestamp
columns:
- name: event_id
description: "UUID do evento"
data_tests:
- not_null
- unique:
config:
severity: warn # duplicatas são esperadas na camada bruta
- name: event_timestamp
description: "Timestamp UTC do evento"
data_tests:
- not_null
- name: users
description: "Registros brutos de usuários do Firehose"
loaded_at_field: _fivetran_synced
freshness:
warn_after: {count: 4, period: hour}
error_after: {count: 24, period: hour}Verificando Frescor de Sources
# Verificar todas as sources
dbt source freshness
# Verificar source específica
dbt source freshness --select source:raw_events
# Incluir no pipeline CI
dbt source freshness && dbt run --select stagingSources Externas do Redshift Spectrum
Sources podem apontar para tabelas externas do Redshift Spectrum (dados no S3):
sources:
- name: spectrum_raw
description: "Tabelas externas via Redshift Spectrum apontando para data lake no S3"
database: analytics
schema: spectrum_schema # schema externo criado via CREATE EXTERNAL SCHEMA
tables:
- name: events_parquet
description: "Eventos Parquet particionados por ano/mes/dia no S3"
# Sem verificacoes de frescor -- tabelas Spectrum sao particionadas externamente
columns:
- name: event_id
- name: event_timestamp
- name: year
description: "Coluna de particao"
- name: month
description: "Coluna de particao"
- name: day
description: "Coluna de particao"Modelo staging sobre Spectrum:
-- models/staging/stg_spectrum_events.sql
{{ config(
materialized='view',
bind=false -- OBRIGATORIO para sources Spectrum
) }}
select
event_id,
user_id,
event_type,
event_timestamp::timestamp as event_timestamp,
properties::super as properties
from {{ source('spectrum_raw', 'events_parquet') }}
where year = date_part('year', current_date)
and month = date_part('month', current_date)
and day = date_part('day', current_date)Views que referenciam tabelas externas do Redshift Spectrum devem usar bind: false (late-binding views). Views vinculadas padrao nao podem referenciar tabelas externas e falharao com um erro de compilacao.
6 Perguntas de Pratica
O que `dbt_valid_to_current: '9999-12-31'` faz em uma configuracao de snapshot?
Qual e o proposito de `snapshot_meta_column_names` na configuracao de snapshot do dbt 1.9+?
Por que views sobre tabelas externas do Redshift Spectrum devem usar `bind: false`?
Qual estrategia de snapshot voce deve usar quando a tabela fonte nao tem uma coluna `updated_at` mas voce quer detectar qualquer mudanca no valor da coluna?
Você tem um arquivo seed com 800 linhas de codigos de paises que raramente mudam. Deve definir dist: all ou dist: even?
Principais Conclusoes
- dbt 1.9+ permite que snapshots sejam declarados inteiramente em YAML com
snapshot_meta_column_namespara nomenclatura personalizada de colunas edbt_valid_to_currentpara indicadores de registro atual amigos de BI. - Use
strategy: timestampquando uma colunaupdated_atconfiavel existe; usestrategy: checkquando voce precisa de deteccao de mudanca baseada em hash. - Defina
invalidate_hard_deletes: truepara fechar registros historicos quando linhas desaparecem da fonte. - Seeds sao ideais para dados de referencia pequenos e que mudam raramente (<1.000 linhas). Use
dist: allpara que todo join com o seed seja co-localizado. - Filtros de frescor de source (
freshness.filter) limitam consultas de verificacao de frescor a particoes recentes -- essencial para tabelas brutas grandes particionadas por tempo. - Views sobre tabelas externas do Redshift Spectrum requerem
bind: false-- views padrao nao podem referenciar tabelas externas.