Volver a la biblioteca
Artículointermedio

SCD Tipo 2: cómo mantener historia en dimensiones sin volverte loco

SCD Tipo 2 es el patrón estándar para mantener historia en dimensiones, pero tiene complejidad operativa real. Hay que entender cuándo vale la pena y cuándo no.

En el modelo transaccional, cuando un cliente cambia de dirección, se hace un UPDATE y listo. El valor anterior desaparece. Para la aplicación eso está bien: lo que importa es el estado actual.

Pero en analítica, perder ese historial puede ser un problema. Si querés saber cuántas ventas se hicieron a clientes de determinada región el año pasado, necesitás saber dónde vivía cada cliente en ese momento, no dónde vive hoy.

Las dimensiones lentamente cambiantes (Slowly Changing Dimensions o SCD) son el patrón que Kimball propuso para resolver esto. Y el Tipo 2 es el más usado cuando necesitás mantener historia completa.

Qué hace SCD Tipo 2

La idea es simple: en lugar de actualizar un registro cuando cambia un atributo, insertás uno nuevo. Cada versión del registro tiene su propia clave subrogada y un rango de validez.

Por ejemplo, si un cliente cambia de dirección:

sk_clientecliente_idnombredireccionvalid_fromvalid_tois_current
1C001Juan PérezAv. Corrientes 12342024-01-012025-03-14false
2C001Juan PérezAv. Santa Fe 56782025-03-159999-12-31true

La clave de negocio (cliente_id) es la misma en ambos registros. Pero hay dos filas: una histórica (cerrada) y una vigente. Cuando la tabla de hechos referencia sk_cliente = 1, está apuntando a la versión del cliente que vivía en Corrientes.

Una dimensión con SCD Tipo 2 tiene esta estructura:

  • sk_cliente: clave subrogada (puede ser un hash o un autoincremental).
  • cliente_id: clave natural de origen.
  • nombre, email, direccion: atributos del cliente.
  • valid_from: fecha desde la que esta versión es válida.
  • valid_to: fecha hasta la que esta versión fue válida.
  • is_current: flag que indica si es la versión vigente.

Cuando un cliente cambia de dirección, el proceso hace dos cosas: cierra el registro anterior (seteando valid_to y is_current = false) e inserta uno nuevo con la dirección actualizada.

El resultado es que para un mismo cliente_id podés tener múltiples registros, cada uno representando una versión histórica.

Por qué sirve para analítica

Cuando la tabla de hechos referencia a la dimensión, lo hace a través de la clave subrogada. Eso significa que cada hecho queda asociado a la versión de la dimensión que estaba vigente en ese momento.

Si un cliente vivía en Buenos Aires cuando hizo una compra en marzo y después se mudó a Córdoba, la compra de marzo sigue apuntando a la versión "Buenos Aires" del cliente. Las compras posteriores apuntan a la versión "Córdoba".

Esto permite responder preguntas como:

  • Cuántas ventas se hicieron a clientes de cada región, según dónde vivían al momento de la compra.
  • Cómo evolucionó la distribución geográfica de las ventas a lo largo del tiempo.
  • Qué clientes cambiaron de segmento y cuándo.

Sin SCD Tipo 2, todas las ventas históricas quedarían asociadas a la dirección actual del cliente, distorsionando el análisis.

La complejidad operativa

Hasta acá suena razonable. El problema es que implementar y mantener SCD Tipo 2 tiene costos que no son obvios al principio.

El proceso de carga se complica. En lugar de un simple INSERT o UPDATE, tenés que detectar cambios, cerrar registros anteriores e insertar nuevos. Esto requiere comparar el estado actual de la dimensión con los datos de origen, identificar qué cambió, y ejecutar una operación de dos pasos (UPDATE + INSERT) que conviene meter en una transacción para evitar inconsistencias.

La dimensión crece. Cada cambio en un atributo trackeado genera un registro nuevo. Si tenés 100.000 clientes y el 10% cambia de dirección por año, en cinco años tenés 150.000 registros en lugar de 100.000. Con atributos que cambian más frecuentemente, el crecimiento puede ser mucho mayor.

Los joins se vuelven más lentos. Más registros en la dimensión significa más trabajo para el motor de base de datos al hacer joins con la tabla de hechos. En dimensiones grandes con muchas versiones, esto puede impactar la performance de las consultas.

La clave subrogada importa. Si usás un autoincremental, tenés que tener cuidado con las recargas. Si borrás y volvés a cargar la dimensión, los autoincrementales pueden cambiar y perdés la referencia desde las tablas de hechos. Por eso muchos equipos usan hashes determinísticos: el hash de los atributos trackeados siempre da el mismo resultado para los mismos valores.

Cuándo vale la pena

SCD Tipo 2 tiene sentido cuando:

  • El atributo que cambia es analíticamente relevante. Si nadie va a preguntar "cuántas ventas por región histórica", no tiene sentido trackear cambios de dirección.
  • Los cambios son relativamente infrecuentes. Por eso se llaman "lentamente cambiantes". Si un atributo cambia todos los días, SCD Tipo 2 genera una explosión de registros.
  • Necesitás el historial completo. Si solo te importa el valor actual y el anterior, hay alternativas más simples.

Cuándo no vale la pena

Atributos que cambian muy seguido. Si un atributo cambia con alta frecuencia (por ejemplo, un score de riesgo que se recalcula diariamente), SCD Tipo 2 genera dimensiones enormes. Kimball propone para estos casos la mini-dimensión: sacar los atributos volátiles a una dimensión separada que se maneja de forma distinta.

Atributos que nadie va a analizar históricamente. Si el email del cliente cambia y a nadie le importa cuál era el email anterior, no tiene sentido trackearlo. Podés usar SCD Tipo 1 (sobrescribir el valor) para esos atributos y reservar Tipo 2 solo para los que importan.

Cuando la complejidad no se justifica. En equipos chicos o proyectos en etapa temprana, a veces conviene empezar con Tipo 1 y migrar a Tipo 2 cuando aparece la necesidad real. Implementar SCD Tipo 2 desde el día uno para atributos que quizás nunca se analicen históricamente es sobreingeniería.

Tipo 1, Tipo 2 y el híbrido

En la práctica, muchas dimensiones combinan ambos tipos:

  • Tipo 1 para atributos que se pueden sobrescribir sin perder información valiosa (correcciones de errores, datos que no tienen relevancia histórica).
  • Tipo 2 para atributos donde el historial importa (segmento de cliente, categoría de producto, ubicación geográfica).

Esto requiere que el proceso de carga distinga qué tipo de cambio ocurrió y actúe en consecuencia. Un cambio en el email puede ser Tipo 1 (sobrescribir), mientras que un cambio en el tipo de suscripción puede ser Tipo 2 (versionar).

Implementación práctica

El proceso de carga incremental para una dimensión Tipo 2 tiene esta estructura:

  1. Comparar los datos de origen con la versión actual de la dimensión (donde es_actual = true).
  2. Identificar registros nuevos (no existen en la dimensión) y registros con cambios en atributos Tipo 2.
  3. Para los que tienen cambios: hacer UPDATE del registro actual (setear valido_hasta, es_actual = false).
  4. Insertar los registros nuevos y las nuevas versiones de los que cambiaron.

Conviene meter todo en una transacción. Si el UPDATE se ejecuta pero el INSERT falla, la dimensión queda en estado inconsistente: el registro anterior está cerrado pero no existe el nuevo.

En herramientas como dbt, los snapshots implementan esta lógica de forma declarativa. Definís qué columnas querés trackear y la herramienta se encarga del resto.

El costo de no hacerlo bien

Si implementás SCD Tipo 2 sin pensar en los trade-offs, podés terminar con:

  • Dimensiones que crecen sin control porque trackeás cambios en atributos que no importan.
  • Procesos de carga lentos porque la comparación entre origen y dimensión se vuelve pesada.
  • Consultas lentas porque los joins con dimensiones infladas tardan más.
  • Inconsistencias si el proceso de carga no maneja bien los errores.

Y si no lo implementás cuando lo necesitás, perdés la capacidad de hacer análisis histórico preciso. Todas las métricas quedan distorsionadas por el estado actual de las dimensiones.

En resumen

SCD Tipo 2 es el patrón estándar para mantener historia en dimensiones. Permite que cada hecho quede asociado a la versión de la dimensión que estaba vigente en ese momento, lo cual es fundamental para análisis histórico preciso.

Pero tiene complejidad operativa: el proceso de carga es más complejo, la dimensión crece con cada cambio, y hay que tener cuidado con la clave subrogada.

La recomendación es aplicarlo selectivamente: solo para atributos donde el historial tiene valor analítico real, y solo cuando la frecuencia de cambios es manejable. Para atributos que cambian muy seguido, hay alternativas como la mini-dimensión. Para atributos sin relevancia histórica, Tipo 1 es suficiente.

Como con casi todo en modelado, la respuesta correcta depende del contexto. Pero entender bien el patrón y sus costos te permite tomar esa decisión con fundamento.