dbt: transformação como código, testável
⏱ 14 min·⭐ 60 XP
Pré-requisitos (0/1)0%
- ⬜⏱️ Batch vs stream: mental model e trade-offs reais(Data Engineering Moderna)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
Estrutura de projeto dbt
| Camada | Responsabilidade | Regra |
|---|---|---|
| Fonte | Declarar de onde vem o dado bruto | Nunca transforma — só nomeia e testa frescor |
| Preparação | Renomear, tipar, limpar | Um modelo por tabela de origem; sem junção |
| Intermediária | Junções e regras reutilizáveis | Não é consumida por painel |
| Marts | Modelo de negócio, pronto para consumo | É o contrato com quem analisa |
| ⚠ Teste | Unicidade, não-nulo, relacionamento, valores aceitos | Sem teste, transformação como código é só SQL em pasta |
CamadaFonte
ResponsabilidadeDeclarar de onde vem o dado bruto
RegraNunca transforma — só nomeia e testa frescor
CamadaPreparação
ResponsabilidadeRenomear, tipar, limpar
RegraUm modelo por tabela de origem; sem junção
CamadaIntermediária
ResponsabilidadeJunções e regras reutilizáveis
RegraNão é consumida por painel
CamadaMarts
ResponsabilidadeModelo de negócio, pronto para consumo
RegraÉ o contrato com quem analisa
Camada⚠ Teste
ResponsabilidadeUnicidade, não-nulo, relacionamento, valores aceitos
RegraSem teste, transformação como código é só SQL em pasta
models/
staging/ # raw → cleaned (1:1)
stg_users.sql
stg_orders.sql
marts/ # business logic
finance/
orders_daily.sql
growth/
user_cohorts.sql
schema.yml # tests + docs
sources.yml # declara raw tables
dbt_project.ymlModel exemplo
-- models/marts/finance/orders_daily.sql
{{ config(materialized='table') }}
SELECT
DATE_TRUNC('day', o.created_at) AS day,
COUNT(*) AS orders,
SUM(o.total) AS revenue,
COUNT(DISTINCT u.id) AS unique_users
FROM {{ ref('stg_orders') }} o
JOIN {{ ref('stg_users') }} u ON o.user_id = u.id
WHERE o.status = 'paid'
GROUP BY 1
-- schema.yml
version: 2
models:
- name: orders_daily
columns:
- name: day
tests: [unique, not_null]
- name: revenue
tests:
- dbt_utils.expression_is_true:
expression: ">= 0"Quiz rápido
Qual é a mudança central ao tratar transformação de dados como código?
Materializations
- view (default): não persiste, re-executa em query
- table: materializa full rebuild
- incremental: só processa dados novos (configurar unique_key + where)
- ephemeral: CTE inline (não cria objeto no DB)
💡
Core (CLI open) vs Cloud (web IDE, scheduler, lineage, alerts). Cloud é pago mas vale pra times não-dev (analistas). Core roda em Airflow/Dagster/GitHub Actions com cron.
Perguntas frequentes
❓ O que o dbt resolve que SQL solto não resolve?
Versionamento, dependência entre transformações, teste e documentação no mesmo lugar. O SQL continua sendo SQL; o que muda é o processo — a transformação passa a ter revisão de código, histórico e execução reproduzível. É engenharia de software aplicada ao dado.
❓ Qual a diferença entre modelo materializado e visão?
A visão recalcula a cada consulta e não ocupa espaço; a tabela materializada é calculada uma vez e lida rápido. Incremental é o meio: processa só o que chegou. A decisão é de custo de consulta contra custo de processamento, e muda conforme o modelo é consultado.
❓ Teste de dado substitui teste de código?
Não: são camadas diferentes. Teste de código verifica a transformação; teste de dado verifica a premissa sobre o dado — unicidade, não nulo, faixa, integridade referencial. A maior parte dos incidentes de pipeline é de premissa violada, não de lógica errada.
Fixando
Quiz rápido
O que a escolha de materialização decide, na prática?
Quiz rápido
Por que testes de dados são diferentes de testes de código?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…