En 2025, si construyes un Data Warehouse sin dbt, estás eligiendo el camino difícil. dbt (data build tool) ha ganado el mercado de transformaciones ELT de forma aplastante. No porque sea perfecto, sino porque resuelve un problema real que cualquier equipo de datos ha sufrido: cómo gestionar transformaciones SQL de forma profesional, versionada y probada.
Por qué dbt ha ganado el mercado
Antes de dbt, el flujo típico era: un analista escribía SQL en un editor, lo pegaba en el DWH, y nadie sabía de dónde venían los datos ni quién los había transformado. dbt cambió esto introduciendo:
- Modelos SQL versionados en Git: cada transformación es un fichero .sql bajo control de versiones
- Gestión automática de dependencias: dbt calcula el orden correcto de ejecución usando un DAG
- Tests integrados: validación de datos como parte del pipeline
- Documentación automática: genera un portal web con el linaje de todos los modelos
- Jinja templating: lógica dinámica dentro del SQL sin cambiar de lenguaje
“dbt les da a los ingenieros de datos las mejores prácticas de ingeniería de software: tests, documentación, modularidad y control de versiones. Todo aplicado a SQL.”
dbt Core vs dbt Cloud
| Característica | dbt Core | dbt Cloud |
|---|---|---|
| Precio | Gratuito (open source) | Desde 50 USD/usuario/mes |
| Interfaz | CLI únicamente | IDE web + CLI |
| Orquestación | Manual / Airflow | Jobs gestionados |
| Alertas y monitoreo | No incluido | Incluido |
| CI/CD integrado | Requiere configuración | Nativo (GitHub/GitLab) |
| Mejor para | Equipos pequeños, experimentación | Equipos medianos/grandes |
Arquitectura de un proyecto dbt
mi_proyecto_dbt/
|-- dbt_project.yml # configuracion del proyecto
|-- profiles.yml # conexion al DWH (fuera del repo)
|-- models/
| |-- staging/ # fuentes en bruto, 1:1 con tablas origen
| | |-- stg_ventas.sql
| | |-- stg_clientes.sql
| | |-- _sources.yml # definicion de fuentes
| |-- intermediate/ # calculos intermedios, no expuestos
| | |-- int_ventas_enriquecidas.sql
| |-- marts/ # tablas finales para BI
| | |-- ventas/
| | | |-- fct_ventas.sql
| | | |-- dim_cliente.sql
| | | |-- _schema.yml # tests y documentacion
|-- seeds/ # CSVs estaticos
|-- macros/ # funciones SQL reutilizables
|-- tests/ # tests singulares (SQL custom)
|-- snapshots/ # SCD tipo 2 (historial de cambios)
Ejemplo de modelo con Jinja
-- models/staging/stg_ventas.sql
{{ config(materialized='view') }}
WITH source AS (
SELECT * FROM {{ source('raw', 'ventas') }}
),
renamed AS (
SELECT
CAST(id_venta AS STRING) AS venta_id,
CAST(id_cliente AS STRING) AS cliente_id,
CAST(id_producto AS STRING) AS producto_id,
DATE(fecha_venta) AS fecha_venta,
CAST(cantidad AS INT64) AS cantidad,
CAST(precio_unitario AS FLOAT64) AS precio_unitario,
CAST(descuento AS FLOAT64) AS descuento,
cantidad * precio_unitario * (1 - descuento) AS importe_neto,
_PARTITIONDATE AS fecha_carga
FROM source
WHERE fecha_venta IS NOT NULL
AND cantidad > 0
)
SELECT * FROM renamed
Tests genéricos en schema.yml
# models/marts/ventas/_schema.yml
version: 2
models:
- name: fct_ventas
description: "Tabla de hechos de ventas. Una fila por linea de pedido."
columns:
- name: venta_id
tests:
- unique
- not_null
- name: cliente_id
tests:
- not_null
- relationships:
to: ref('dim_cliente')
field: cliente_id
- name: importe_neto
tests:
- not_null
- dbt_utils.accepted_range:
min_value: 0
Despliegue en GCP BigQuery (paso a paso)
# 1. Instalar dbt con el adaptador de BigQuery
pip install dbt-bigquery
# 2. Configurar profiles.yml (~/.dbt/profiles.yml)
my_project:
target: dev
outputs:
dev:
type: bigquery
method: oauth
project: mi-proyecto-gcp
dataset: dbt_dev
threads: 4
prod:
type: bigquery
method: service-account
project: mi-proyecto-gcp
dataset: dbt_prod
keyfile: /path/to/service-account.json
threads: 8
# 3. Verificar conexion
dbt debug
# 4. Ejecutar todos los modelos
dbt run
# 5. Ejecutar tests
dbt test
# 6. Generar documentacion
dbt docs generate
dbt docs serve
Despliegue en Azure Synapse / Azure SQL
# 1. Instalar adaptador de Synapse
pip install dbt-synapse
# 2. Configurar profiles.yml para Synapse
my_project:
target: dev
outputs:
dev:
type: synapse
driver: 'ODBC Driver 18 for SQL Server'
server: mi-workspace.sql.azuresynapse.net
port: 1433
database: mi_dedicated_pool
schema: dbt_dev
authentication: ServicePrincipal
tenant_id: "xxxx-xxxx-xxxx"
client_id: "xxxx-xxxx-xxxx"
client_secret: "{{ env_var('DBT_AZURE_CLIENT_SECRET') }}"
threads: 4
# 3. Ejecutar solo modelos de staging
dbt run --select staging
# 4. Ejecutar con full-refresh (reconstruir desde cero)
dbt run --full-refresh
Integración con Apache Airflow
from airflow import DAG
from airflow.operators.bash import BashOperator
from datetime import datetime
with DAG(
dag_id='dbt_daily_run',
schedule_interval='0 6 * * *',
start_date=datetime(2025, 1, 1),
catchup=False,
tags=['dbt', 'datawarehouse']
) as dag:
dbt_run = BashOperator(
task_id='dbt_run',
bash_command='cd /opt/dbt/mi_proyecto && dbt run --target prod',
env={'DBT_PROFILES_DIR': '/opt/dbt/profiles'}
)
dbt_test = BashOperator(
task_id='dbt_test',
bash_command='cd /opt/dbt/mi_proyecto && dbt test --target prod'
)
dbt_run >> dbt_test
Usa el proveedor oficial apache-airflow-providers-dbt-cloud si usas dbt Cloud. Para dbt Core, el BashOperator es la opción más portable. El paquete astronomer-cosmos convierte cada modelo dbt en una tarea Airflow individual para mayor observabilidad.
dbt Starter Kit para BigQuery y Snowflake
Proyecto dbt completo con estructura de carpetas, modelos de staging y marts, tests genéricos preconfigurados, macros de utilidad y documentación. Listo para arrancar en horas, no semanas.
Ver recursos →