dbt: transformando dados com SQL e Python
Se você trabalha com dados, provavelmente passa mais tempo transformando do que extraindo. O dbt (Data Build Tool) é a ferramenta que trouxe práticas de engenharia de software para o mundo de transformação de dados: versionamento, testes, documentação e modularity — tudo em SQL.
O que é dbt?
dbt é uma ferramenta open-source que permite transformar dados no warehouse usando SQL SELECT statements. Em vez de escrever scripts ETL complexos, você escreve queries SQL e o dbt cuida de:
- Materializar como tabelas ou views
- Gerenciar dependências entre models
- Rodar testes de qualidade
- Gerar documentação automática
O fluxo é: Extract & Load (ferramentas como Airbyte, Fivetran) → Transform (dbt).
Instalação
pip install dbt-core
# ou, para PostgreSQL:
pip install dbt-postgres
# para BigQuery:
pip install dbt-bigquery
Inicializando um projeto
dbt init meu_projeto
cd meu_projeto
Estrutura criada:
meu_projeto/
├── dbt_project.yml # Configuração do projeto
├── models/ # Queries SQL
│ ├── staging/ # Models de staging (limpeza)
│ └── marts/ # Models finais (analytics)
├── tests/ # Testes customizados
├── macros/ # Funções SQL reutilizáveis
└── seeds/ # CSVs para carregar dados estáticos
Escrevendo models
Cada model é um arquivo .sql com um SELECT. O dbt materializa como view ou tabela.
Staging: limpando dados brutos
-- models/staging/stg_pedidos.sql
with source as (
select * from
),
cleaned as (
select
id,
cliente_id,
valor,
status,
created_at::date as data_pedido,
case
when status = 'completed' then 'concluido'
when status = 'pending' then 'pendente'
when status = 'cancelled' then 'cancelado'
else 'desconhecido'
end as status_traduzido
from source
where valor > 0
and created_at >= '2020-01-01'
)
select * from cleaned
O `` é uma Jinja template — dbt injeta o nome correto da tabela.
Mart: dados prontos para análise
-- models/marts/fct_vendas.sql
with pedidos as (
select * from
),
clientes as (
select * from
),
vendas as (
select
p.id as pedido_id,
p.data_pedido,
c.nome as cliente_nome,
c.estado as cliente_estado,
p.valor,
p.status_traduzido
from pedidos p
inner join clientes c on p.cliente_id = c.id
where p.status_traduzido = 'concluido'
)
select * from vendas
O `` cria uma dependência — dbt sabe que stg_pedidos deve rodar antes de fct_vendas.
Materializações
Controla como o model é persistido no warehouse:
# dbt_project.yml
models:
meu_projeto:
staging:
+materialized: view
marts:
+materialized: table
Opções:
| Tipo | Quando usar |
|---|---|
view |
Staging, dados que mudam frequentemente |
table |
Marts, dados que são caros de calcular |
incremental |
Grandes volumes, append de dados novos |
Incremental models
Para tabelas grandes, processe apenas dados novos:
-- models/marts/fct_eventos.sql
{{
config(
materialized='incremental',
unique_key='evento_id'
)
}}
select
evento_id,
usuario_id,
tipo,
timestamp
from {{ ref('stg_eventos') }}
{% if is_incremental() %}
where timestamp > (select max(timestamp) from {{ this }})
{% endif %}
Testes
dbt vem com testes genéricos e suporta testes customizados:
# models/staging/stg_pedidos.yml
version: 2
models:
- name: stg_pedidos
columns:
- name: id
tests:
- unique
- not_null
- name: valor
tests:
- not_null
- dbt_utils.accepted_range:
min_value: 0
max_value: 1000000
- name: status_traduzido
tests:
- accepted_values:
values: ['concluido', 'pendente', 'cancelado']
Execute os testes:
dbt test
Documentação automática
Gere docs interativas com um comando:
dbt docs generate
dbt docs serve
Isso abre uma interface web em localhost:8080 com:
- Grafo de dependências entre models
- Descrição de cada coluna
- Testes associados
- SQL de cada model
Macros: SQL reutilizável
-- macros/formata_moeda.sql
{% macro formata_moeda(coluna) %}
'R$ ' || to_char({{ coluna }}, 'FM999G999G999D00')
{% endmacro %}
-- Uso em um model
select
pedido_id,
{{ formata_moeda('valor') }} as valor_formatado
from {{ ref('stg_pedidos') }}
Comandos essenciais
# Rodar todos os models
dbt run
# Rodar um model específico
dbt run --select stg_pedidos
# Rodar um model e seus downstream
dbt run --select fct_vendas+
# Rodar testes
dbt test
# Seed (carregar CSVs)
dbt seed
# Snapshot (Type 2 SCD)
dbt snapshot
# Documentação
dbt docs generate
dbt docs serve
# Debug de conexão
dbt debug
Conclusão
dbt mudou a forma como pensamos sobre transformação de dados. Em vez de scripts ETL frágeis, temos SQL versionado, testado e documentado. A curva de aprendizado é baixa — se você sabe SQL, já sabe usar dbt.
Comece com um projeto simples: crie 2-3 staging models e 1 mart. Adicione testes e documentação. Em poucas horas, terá um pipeline de dados profissional.
Caso eu tenha falado alguma besteira, por favor, agradecerei correções e sugestões.