Logo GCP con Eduardo

GCP con Eduardo

Descarga el código de la lección

Estructura de Modelos en dbt: Marts, Capa Dimensional y Materializaciones (View vs Table)
✦ Guía Técnica & Arquitectura

Estructura de Modelos en dbt: Marts, Capa Dimensional y Materializaciones (View vs Table)

Diseñar modelos en dbt a escala empresarial no consiste simplemente en transformar SQL. La verdadera decisión arquitectónica está en definir contratos de datos, separar responsabilidades, construir una capa marts dbt consumible y elegir correctamente entre view, table e incremental según volumen, frecuencia de consulta, coste y criticidad.

En esta guía de nivel Senior / Staff / Architect construiremos un patrón de modelado dimensional con fact tables dbt, dimensiones, ref(), materializaciones y controles orientados a producción.

Lo que aprenderás

El objetivo es pasar de un proyecto dbt organizado por archivos SQL a una arquitectura de transformación explícita, gobernable y preparada para crecer.

Modelado dimensional Diseña dimensiones y hechos con granularidad explícita.
Marts orientados al consumo Construye interfaces analíticas estables para BI y ciencia de datos.
View vs Table Selecciona materializaciones según coste, frecuencia y complejidad.
ref() y lineage Gestiona dependencias de forma declarativa y desacoplada.

Stack tecnológico

El patrón es independiente del warehouse, aunque las decisiones físicas de rendimiento deben adaptarse al motor analítico utilizado.

dbt dbt Core SQL Jinja Dimensional Modeling Fact Tables Data Warehouse Analytics Engineering Data Quality FinOps

Matriz de decisión arquitectónica

La materialización no debería elegirse por costumbre. Debe responder al patrón de acceso, al tamaño del modelo, a la frecuencia de ejecución y al coste computacional.

Patrón Persistencia Latencia de consulta Coste de construcción Uso recomendado
View Definición lógica Depende de la complejidad Bajo durante el build Transformaciones ligeras y modelos de bajo volumen de consumo.
Table Datos persistidos Generalmente predecible Mayor durante el build Marts, dimensiones y modelos consultados frecuentemente.
Incremental Datos persistidos parcialmente actualizados Generalmente predecible Optimizable según estrategia Fact tables grandes y cargas donde recalcular todo sería innecesariamente caro.
Ephemeral No crea una relación persistente independiente Depende del SQL final Se incorpora al modelo consumidor Lógica intermedia reutilizable que no necesita ser consultada directamente.

Arquitectura recomendada: Staging → Intermediate → Marts

Una arquitectura mantenible separa la normalización de fuentes, la lógica de transformación y la interfaz final de consumo.

staging

Normalización de fuentes

El objetivo es convertir fuentes operacionales en una representación coherente y predecible para las capas posteriores.

  • Renombrado consistente.
  • Tipado y casting.
  • Normalización de timestamps.
  • Eliminación de ruido técnico.
intermediate

Lógica de transformación

Aquí se encapsulan joins, deduplicaciones, enriquecimientos y reglas complejas que no deberían contaminar los marts.

  • Deduplicación.
  • Construcción de entidades.
  • Reglas de negocio reutilizables.
  • Agregaciones intermedias.
marts

Interfaz analítica

La capa marts expone modelos orientados al negocio y optimizados para sus consumidores.

  • Dimensiones.
  • Fact tables.
  • Métricas y KPIs.
  • Contratos de consumo.

Capa dimensional: dimensiones y fact tables

El error más frecuente es diseñar los marts como simples copias de las fuentes. Un modelo dimensional debe partir de una pregunta analítica y, sobre todo, de una granularidad definida.

Ejemplo de definición de granularidad

Supongamos que construimos fct_orders. Antes de escribir SQL debemos poder completar esta frase:

“Cada fila de fct_orders representa exactamente una línea de pedido confirmada.”

Esa decisión determina las claves, los joins, los agregados y las pruebas de calidad. Si una dimensión contiene múltiples registros para la misma clave durante el join, la fact table puede sufrir multiplicaciones silenciosas de filas.

Antipatrones críticos y FinOps

En producción, muchos problemas atribuidos al warehouse son realmente problemas de diseño del grafo de transformación.

⚠ Antipatrón: convertir todo en views

Utilizar views para absolutamente todos los modelos puede parecer barato porque el build de dbt es ligero. Sin embargo, una view compleja puede trasladar el coste al momento de cada consulta.

Si un mart es consultado cientos o miles de veces al día y contiene joins, ventanas, deduplicaciones o agregaciones costosas, el coste computacional puede repetirse innecesariamente.

La solución no es convertir todo en tables. La solución es medir el patrón de consumo y seleccionar la materialización adecuada.

Regla arquitectónica: materializa como table los modelos que funcionan como interfaces analíticas estables y son consultados repetidamente; reserva view para lógica ligera o casos donde la persistencia no aporta suficiente valor.

ref(): el contrato entre modelos

La función ref() es una de las piezas fundamentales de dbt porque expresa dependencias entre modelos sin acoplar el SQL a nombres físicos.

Por qué evitar referencias físicas

Un SQL como FROM analytics.raw_orders acopla el modelo al nombre y al entorno físico de una tabla.

En cambio, FROM {{ ref('stg_orders') }} declara que el modelo actual depende de stg_orders.

Esto permite a dbt construir el grafo de dependencias y resolver las relaciones de forma coherente con el entorno de ejecución.

Implementación práctica de producción

El siguiente patrón separa staging, dimensión y fact table, y utiliza ref() para mantener el lineage explícito.

models/marts/core/fct_orders.sql SQL + Jinja
{{
  config(
    materialized='table',
    tags=['marts', 'core']
  )
}}

with orders as (

    select *
    from {{ ref('stg_orders') }}

),

customers as (

    select
        customer_id,
        customer_key,
        customer_segment
    from {{ ref('dim_customers') }}

),

order_lines as (

    select
        order_id,
        order_line_id,
        customer_id,
        product_id,
        ordered_at,
        quantity,
        unit_price,
        quantity * unit_price as gross_amount
    from {{ ref('int_order_lines') }}

),

final as (

    select
        ol.order_id,
        ol.order_line_id,
        c.customer_key,
        ol.product_id,
        ol.ordered_at,
        ol.quantity,
        ol.unit_price,
        ol.gross_amount
    from order_lines ol
    inner join customers c
        on ol.customer_id = c.customer_id

)

select *
from final

Dónde colocar la configuración

La configuración puede declararse en el propio modelo o centralizarse mediante archivos de configuración del proyecto. Para equipos grandes, la consistencia de convenciones suele ser más importante que una única estrategia universal.

models/marts/core/schema.yml YAML
version: 2

models:

  - name: fct_orders
    description: >
      Una fila por línea de pedido confirmada.

    columns:

      - name: order_line_id
        description: Clave única de la línea de pedido.
        data_tests:
          - not_null
          - unique

      - name: customer_key
        description: Clave dimensional del cliente.
        data_tests:
          - not_null

      - name: gross_amount
        description: Importe bruto de la línea.
        data_tests:
          - not_null

Patrones de diseño y mejores prácticas

Una arquitectura dbt madura no busca únicamente que el SQL funcione. Busca que el sistema pueda evolucionar sin convertir cada cambio en una operación de alto riesgo.

1. Contratos claros

Cada modelo de marts debe tener una responsabilidad concreta, nombres estables, granularidad documentada y columnas con significado empresarial.

2. Dependencias explícitas

Utiliza ref() para modelos internos y evita referencias físicas que oculten dependencias dentro del grafo.

3. Separación de responsabilidades

No conviertas un único modelo en un monolito de 1.500 líneas. Divide lógica compleja cuando exista una frontera semántica real.

4. Grain first

Define la granularidad antes de realizar joins. La mayoría de los errores graves de fact tables proceden de duplicaciones no detectadas.

5. Materialización basada en evidencia

Mide volumen, frecuencia de consulta, coste y SLA antes de decidir entre view, table o incremental.

6. Gobernanza integrada

Tests, documentación, ownership, naming conventions y lineage deben formar parte de la definición del modelo, no ser tareas posteriores.

Cuándo escalar hacia incremental

Una fact table que crece continuamente puede convertirse en el principal consumidor de recursos del proyecto si se reconstruye completamente en cada ejecución.

La pregunta correcta

No preguntes únicamente: “¿Esta tabla es grande?”

Pregunta: “¿Puedo identificar de forma fiable qué registros nuevos o modificados necesito procesar sin comprometer la corrección histórica?”

Una estrategia incremental requiere conocer las características de actualización de la fuente, la disponibilidad de una clave o timestamp adecuado, la posibilidad de late-arriving data y la estrategia de corrección de registros históricos.

Framework de implementación paso a paso

Este checklist permite introducir una arquitectura de marts sin empezar por una refactorización masiva.

Define el dominio

Determina qué área de negocio representa el mart: ventas, clientes, producto, finanzas, operaciones, marketing, etc.

Define la granularidad

Escribe explícitamente qué representa una fila de cada fact table y dimensión. Esta decisión debe preceder a los joins.

Normaliza staging

Limpia nombres, tipos, timestamps y convenciones sin introducir todavía reglas de negocio complejas.

Extrae lógica intermedia

Aísla deduplicaciones, joins complejos y transformaciones reutilizables en modelos intermedios.

Construye dimensiones

Define claves, atributos, estrategia histórica y reglas de unicidad antes de conectar las dimensiones con los hechos.

Construye fact tables

Usa la granularidad definida y controla explícitamente la cardinalidad de cada join.

Selecciona materialización

Comienza con una decisión simple y evoluciona hacia table o incremental cuando los datos de consumo lo justifiquen.

Añade observabilidad

Mide duración de builds, volumen procesado, fallos de tests, coste computacional y frecuencia de consumo.

Documenta el contrato

Documenta propósito, owner, granularidad, columnas críticas, SLA y consumidores principales.

Preguntas frecuentes sobre modelos en dbt

Respuestas orientadas a las decisiones que aparecen con mayor frecuencia al diseñar una arquitectura dbt empresarial.

¿Cuándo conviene usar table frente a view en dbt?

Una table suele ser preferible cuando el modelo se consulta frecuentemente, contiene transformaciones costosas o actúa como una interfaz estable para consumidores analíticos. Una view puede ser adecuada cuando se necesita lógica ligera, baja latencia de despliegue y se acepta ejecutar la transformación durante la consulta.

¿Por qué se recomienda utilizar ref() en los modelos de dbt?

ref() crea una referencia declarativa entre modelos, permite construir el grafo de dependencias y evita acoplar el SQL a nombres físicos de tablas generados por un entorno concreto.

¿Cómo debería estructurarse una capa marts en dbt?

Una capa marts debería exponer modelos orientados al consumo, normalmente organizados alrededor de hechos y dimensiones. La lógica compleja debería dividirse en capas intermedias para mantener contratos claros, reutilización, trazabilidad y menor acoplamiento.

Sobre el Autor: Eduardo Martínez Agrelo

AI & Data Architect

Eduardo Martínez Agrelo es AI & Data Architect, especializado en arquitectura de datos, inteligencia artificial y diseño de plataformas analíticas. Su enfoque combina profundidad técnica, pensamiento arquitectónico y pragmatismo de producción, con especial atención a escalabilidad, gobierno, rendimiento y eficiencia de costes.

Este contenido está orientado a profesionales Senior, Staff y Architects que necesitan convertir patrones de ingeniería de datos en sistemas mantenibles y preparados para crecer.

© 2026 Eduardo Martínez Agrelo · AI & Data Architect · Arquitectura de Datos, Analytics Engineering e Inteligencia Artificial.