dbt en 2026: transformaciones de datos, pruebas y preguntas de entrevista
Tutorial práctico de dbt (data build tool): transformaciones SQL, modelado por capas, estrategias de pruebas y preguntas reales de entrevista para roles de data engineering en 2026.

dbt (data build tool) se convirtió en el framework estándar para transformar datos dentro de los almacenes modernos, usado en producción por más de 40 000 empresas en 2026. Este tutorial cubre los mecanismos centrales de las transformaciones de dbt, las estrategias de pruebas y las preguntas que realmente surgen en las entrevistas de data engineering.
dbt maneja la T en ELT. Compila sentencias SQL SELECT en DDL (CREATE TABLE, CREATE VIEW, MERGE) y las ejecuta contra un almacén — Snowflake, BigQuery, Redshift o Databricks. El control de versiones, la resolución de dependencias, las pruebas y la documentación vienen integrados.
Modelado por capas: staging, intermedio y marts
Un proyecto dbt bien estructurado separa las transformaciones en tres capas. Este enfoque, popularizado por la comunidad de dbt, impone modelos de responsabilidad única y facilita la depuración.
Los modelos de staging están más cerca de los datos crudos. Su tarea es acotada: renombrar columnas, convertir tipos y filtrar filas basura. Sin uniones, sin agregaciones.
-- models/staging/stg_orders.sql
WITH source AS (
SELECT * FROM {{ source('ecommerce', 'raw_orders') }}
)
SELECT
id AS order_id,
customer_id,
CAST(order_date AS DATE) AS order_date,
CAST(amount AS DECIMAL(10, 2)) AS order_amount,
LOWER(status) AS order_status
FROM source
WHERE id IS NOT NULLLos modelos intermedios aplican lógica de negocio — uniones, agregaciones, funciones de ventana. Referencian los modelos de staging mediante ref(), que registra las dependencias en el DAG.
-- models/intermediate/int_customer_orders.sql
WITH orders AS (
SELECT * FROM {{ ref('stg_orders') }}
),
customers AS (
SELECT * FROM {{ ref('stg_customers') }}
)
SELECT
c.customer_id,
c.customer_name,
COUNT(o.order_id) AS total_orders,
SUM(o.order_amount) AS lifetime_value,
MIN(o.order_date) AS first_order_date,
MAX(o.order_date) AS last_order_date
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.customer_nameLos marts son la capa final de consumo — tablas limpias y documentadas que los tableros y analistas consultan directamente.
Este enfoque por capas significa que una fuente rota solo afecta al staging, no a todo el pipeline. Cada capa puede probarse de forma independiente.
La función ref() y la resolución del DAG
ref() no es un alias. Llamar a {{ ref('stg_orders') }} hace dos cosas: resuelve el nombre de tabla completamente calificado en tiempo de compilación y registra una arista de dependencia en el grafo acíclico dirigido (DAG) de dbt. Sin ref(), dbt no tiene forma de determinar el orden de ejecución.
Un error común es codificar a mano los nombres de tabla en lugar de usar ref(). Esto rompe el seguimiento de dependencias y puede provocar que los modelos se ejecuten antes de que sus dependencias previas estén listas.
-- Malo: referencia codificada a mano, sin seguimiento de dependencias
SELECT * FROM analytics.stg_orders
-- Bueno: ref() registra la dependencia
SELECT * FROM {{ ref('stg_orders') }}El DAG también impulsa funciones como dbt run --select stg_orders+, que ejecuta un modelo y todo lo que está aguas abajo de él — útil para reconstrucciones dirigidas tras un cambio de esquema en la fuente.
Materializaciones: elegir la estrategia de almacenamiento adecuada
dbt ofrece cuatro materializaciones integradas, cada una adecuada para distintos patrones de acceso y volúmenes de datos.
| Materialización | Almacenamiento | Ideal para | Compensación |
|----------------|---------|----------|----------|
| view | Sin almacenamiento (calculada al leer) | Transformaciones ligeras, conjuntos pequeños | Lecturas lentas en datos grandes |
| table | Reconstrucción completa en cada ejecución | Modelos de capa mart, lecturas rápidas | Reconstruye todo, mayor costo |
| incremental | Solo agrega/fusiona filas nuevas | Tablas de hechos grandes, flujos de eventos | Lógica más compleja, requiere unique_key |
| ephemeral | Insertada como CTE, nunca materializada | Lógica reutilizable compartida entre modelos | No consultable directamente |
El valor predeterminado es view. Se sobrescribe en el bloque de config del modelo o en dbt_project.yml:
-- models/marts/fct_daily_revenue.sql
{{
config(
materialized='incremental',
unique_key='revenue_date',
incremental_strategy='merge'
)
}}
SELECT
DATE(order_date) AS revenue_date,
SUM(order_amount) AS daily_revenue,
COUNT(DISTINCT customer_id) AS unique_customers
FROM {{ ref('stg_orders') }}
WHERE order_status = 'completed'
{% if is_incremental() %}
AND order_date > (SELECT MAX(revenue_date) FROM {{ this }})
{% endif %}
GROUP BY DATE(order_date)El bloque is_incremental() solo se ejecuta durante las construcciones incrementales — en una recarga completa (dbt run --full-refresh) se omite y la tabla entera se reconstruye.
¿Listo para aprobar tus entrevistas de Data Engineering?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Probar la calidad de los datos en cada capa
dbt provee dos categorías de pruebas: pruebas genéricas declaradas en YAML y pruebas singulares escritas como archivos SQL independientes que devuelven filas cuando fallan.
Las pruebas genéricas cubren restricciones estructurales:
# models/staging/_stg_models.yml
version: 2
models:
- name: stg_orders
columns:
- name: order_id
tests:
- unique # Sin IDs de pedido duplicados
- not_null # Cada fila tiene un ID de pedido
- name: order_status
tests:
- accepted_values:
values: ['completed', 'pending', 'cancelled', 'refunded']
- name: customer_id
tests:
- not_null
- relationships: # Verificación de integridad referencial
to: ref('stg_customers')
field: customer_idLas pruebas singulares validan reglas de negocio que las genéricas no pueden expresar:
-- tests/assert_revenue_never_negative.sql
-- Devuelve filas donde el ingreso diario es negativo (debería devolver 0 filas)
SELECT
revenue_date,
daily_revenue
FROM {{ ref('fct_daily_revenue') }}
WHERE daily_revenue < 0Las pruebas unitarias, introducidas en dbt 1.8, validan la lógica de transformación con entradas controladas y salidas esperadas — sin necesidad de un almacén. Se ejecutan directamente en la fase de pruebas de dbt.
La estrategia de pruebas debe seguir el flujo de datos: chequeos de frescura y validaciones de conteo de filas a nivel de fuente, pruebas de esquema a nivel de staging (not_null, unique), integridad referencial a nivel intermedio y aserciones de lógica de negocio a nivel de mart.
dbt Core v1.10 y el motor Fusion
dbt Core v1.10 introdujo el flag --sample para los comandos run y build. Este flag aplica un muestreo basado en tiempo a ref() y source(), permitiendo a los desarrolladores validar transformaciones sobre un subconjunto de datos sin el costo de una construcción completa. Útil para iterar sobre modelos respaldados por tablas de hechos de miles de millones de filas.
El motor dbt Fusion, una reescritura desde cero en Rust, ahora es el valor predeterminado para los proyectos nuevos en dbt Cloud sobre Snowflake, BigQuery, Redshift y Databricks. Fusion introduce versionado semántico a partir de la 2.0 y trae mejoras de rendimiento significativas a la compilación y la ejecución.
Otras incorporaciones notables de 2026: la especificación YAML del Semantic Layer para definiciones de métricas centralizadas, Cost Insights (beta) para estimar el cómputo del almacén por modelo, y los paquetes privados nativos ahora en disponibilidad general.
Macros y Jinja para lógica reutilizable
Cuando el mismo patrón SQL aparece en varios modelos, conviene extraerlo a una macro. Las macros son funciones Jinja almacenadas en el directorio macros/.
-- macros/cents_to_dollars.sql
{% macro cents_to_dollars(column_name) %}
ROUND(CAST({{ column_name }} AS DECIMAL(10, 4)) / 100, 2)
{% endmacro %}Llamada en cualquier modelo:
-- models/staging/stg_payments.sql
SELECT
payment_id,
order_id,
{{ cents_to_dollars('amount_cents') }} AS amount_dollars,
payment_method
FROM {{ source('stripe', 'payments') }}Esto mantiene el código DRY. La alternativa — copiar la fórmula de conversión en cada modelo que la necesita — genera carga de mantenimiento e inconsistencias.
Preguntas de entrevista que realmente se hacen
Las entrevistas de data engineering en 2026 evalúan cada vez más el conocimiento de dbt más allá de lo básico. Estas son las preguntas que diferencian a los candidatos, extraídas de patrones vistos en roles de empresas que usan stacks de datos modernos.
P: Un modelo incremental reprocesó toda la tabla durante la noche. ¿Qué pasó?
La causa más común: la columna unique_key contenía valores nulos. Cuando dbt intenta un MERGE sobre una clave nula, la coincidencia falla para cada fila, por lo que inserta duplicados. La segunda causa: alguien ejecutó dbt run --full-refresh sin darse cuenta de que reconstruye la tabla desde cero. La tercera: el filtro is_incremental() referenciaba una columna que aún no existe en la tabla destino (primera ejecución vs. ejecuciones posteriores). La depuración empieza por revisar el SQL compilado en target/compiled/.
P: ¿Cómo deben estructurarse las pruebas por capas en un proyecto dbt de producción?
Los chequeos de frescura de la fuente se ejecutan primero — si la fuente no se actualizó, los modelos aguas abajo no deberían correr sobre datos obsoletos. Las pruebas de staging validan restricciones de esquema: claves primarias (unique + not_null), valores aceptados y conversiones de tipo. Las pruebas intermedias verifican la integridad referencial a través de las uniones. Las pruebas de mart afirman invariantes de negocio: ingreso >= 0, usuarios activos >= usuarios de pago, y la suma de las partes igual al total. Todas las pruebas corren en CI sobre los pull requests contra un esquema de dev, y luego nuevamente tras el despliegue en producción con alertas.
P: ¿Cuándo debe ser un modelo efímero en lugar de una vista?
Los modelos efímeros insertan su SQL como CTE dentro de los modelos consumidores — útil para lógica reutilizable que no necesita consultarse de forma independiente. Las vistas se calculan al leer y existen como objetos consultables. La compensación: los modelos efímeros no pueden probarse directamente (no tienen tabla sobre la cual ejecutar aserciones) ni aparecer en herramientas de linaje de datos. Usar efímeros para lógica auxiliar interna; usar vistas para todo lo que necesite pruebas o monitoreo independiente.
P: Explicar la diferencia entre source() y ref().
source() apunta a tablas crudas definidas en un archivo sources.yml — son tablas que dbt no gestiona. ref() apunta a otros modelos dbt. Ambos registran dependencias en el DAG, pero source() además habilita los chequeos de frescura (dbt source freshness), que ref() no hace. Usar source() para tablas crudas y ref() para todo lo demás no es opcional — es la forma en que dbt sabe qué controla y qué no.
Para un conjunto más amplio de preguntas de entrevista de data engineering, incluyendo temas como la arquitectura de pipelines ETL vs ELT, los módulos de práctica de SharpSkill sobre fundamentos de dbt y patrones avanzados de dbt cubren estos conceptos con ejercicios interactivos.
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Conclusión
- dbt transforma los datos crudos del almacén mediante sentencias SQL SELECT, compiladas automáticamente en DDL — la estructura por capas staging/intermedio/mart mantiene cada modelo enfocado en una sola responsabilidad
- La función
ref()es la columna vertebral de la gestión de dependencias: resuelve los nombres de tabla y construye el DAG que controla el orden de ejecución - Las materializaciones incrementales reducen el costo en tablas grandes, pero requieren un manejo cuidadoso de
unique_key, los valores nulos y el filtrois_incremental() - Las pruebas deben seguir el flujo de datos — frescura de la fuente, restricciones de esquema en staging, integridad referencial en el intermedio, aserciones de lógica de negocio a nivel de mart
- dbt Core v1.10 trae el flag
--samplepara una iteración más rápida, mientras que el motor Fusion (basado en Rust, versión 2.0) ahora es el valor predeterminado en dbt Cloud - Las preguntas de entrevista sobre dbt se centran en depurar fallas reales (reprocesamiento incremental, claves nulas, fuentes obsoletas) en lugar de definiciones — la experiencia práctica con SQL compilado y pipelines de CI importa más que las respuestas memorizadas
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Etiquetas
Compartir
Artículos relacionados

Top 25 Preguntas de Entrevista para Ingenieros de Datos en 2026
Guía completa con las 25 preguntas más importantes para entrevistas de ingeniería de datos en 2026. Incluye SQL avanzado, pipelines ETL/ELT, streaming con Kafka, Spark, orquestación y arquitecturas lakehouse.

ETL vs ELT en 2026: Guía Completa de Arquitectura de Pipelines de Datos
Análisis profundo de las arquitecturas ETL y ELT para pipelines de datos en 2026, incluyendo comparativas de costos, ejemplos de código con dbt y criterios de decisión para data engineers.

Apache Kafka para Ingenieria de Datos: Particiones, Streaming y Pipelines en Tiempo Real
Guia completa de Apache Kafka para ingenieria de datos. Arquitectura KRaft, estrategias de particionamiento, consumer groups, CDC con Debezium, exactly-once semantics y Share Groups con ejemplos en Python.