Datos y analytics: del OLTP al lakehouse
Dos preguntas aparecen en toda empresa: por qué el informe tumbó producción, y por qué el número de mi panel es distinto del tuyo. Las dos tienen la misma causa raíz.
Alguien ejecutó un informe pesado en la base de la aplicación y la latencia del checkout se duplicó. Alguien presentó un número de facturación y otra persona presentó otro. Las dos situaciones vienen del mismo sitio: el dato analítico y el dato transaccional se trataron como si fueran la misma cosa.
OLTP y OLAP: dos mundos
OLTP es la base de la aplicación. Muchas transacciones pequeñas, cada una tocando pocas filas, escritura y lectura mezcladas, latencia de milisegundos. Almacenamiento por fila, porque casi siempre quieres la fila entera.
OLAP es el mundo del análisis. Pocas consultas, cada una barriendo millones de filas y agregando, y toleras segundos. Almacenamiento por columna.
Por qué el columnar lo cambia todo: si quieres la suma de una columna sobre cien millones de filas, en el formato por fila lo lees todo, incluidas las cuarenta columnas que no interesan. En el columnar, lees solo esa columna.
Y como los valores de la misma columna son parecidos, comprimen mucho mejor: diez veces es común. Menos bytes leídos es menos tiempo y, en la nube, literalmente menos dinero, porque el cobro es frecuentemente por byte procesado.
Por eso ejecutar un informe en la base de la aplicación es malo de dos formas: es lento, porque el formato es equivocado; y es peligroso, porque consume el mismo recurso que atiende al cliente que paga.
Los nombres que te vas a encontrar: Parquet y ORC como formato de archivo columnar; DuckDB para análisis local, que es sorprendentemente eficiente; ClickHouse para análisis en tiempo real; BigQuery, Snowflake y Redshift como warehouse gestionado.
OLTP: la base de la aplicación
- Muchas transacciones pequeñas, pocas filas cada una
- Almacenamiento por fila: quieres la fila entera
- Latencia de milisegundos, escritura y lectura mezcladas
- Normalizado: cada hecho vive en un solo sitio
OLAP: el mundo del análisis
- Pocas consultas barriendo millones de filas
- Almacenamiento por columna: lee solo la que interesa
- Comprime diez veces mejor, y en la nube eso es dinero
- Desnormalizado a propósito: esquema estrella
Modelado: normalizar o desnormalizar
En OLTP normalizas. Cada hecho vive en un solo sitio, y evitas anomalías de actualización. La tercera forma normal resuelve casi todo.
Dos trampas frecuentes:
Borrado lógico. Una columna borrado parece inofensiva y contamina todas las consultas para
siempre. Alguien va a olvidar el filtro, y el bug va a ser sutil.
Guardar un valor mutable solo por referencia. El precio del producto cambió, y el pedido de hace dos años ahora muestra el valor equivocado. El pedido guarda el precio practicado, siempre. Eso no es desnormalización indebida: es registro histórico.
En OLAP desnormalizas a propósito. El modelo es el esquema estrella: en el centro, la tabla de hechos, con una fila por evento, las medidas numéricas y las claves. Alrededor, las dimensiones: cliente, producto, tiempo, tienda, cada una ancha y descriptiva.
Funciona porque el analista escribe una unión simple y el motor optimiza bien. Cambias normalización por velocidad y claridad, y en un sistema donde nadie actualiza filas, la duplicación no genera anomalías.
Y el concepto que confunde: dimensión que cambia lentamente, o SCD. El cliente cambió de ciudad.
Tipo 1: sobrescribes y pierdes la historia, y el informe del año pasado pasa a mostrar la ciudad nueva.
Tipo 2: creas una fila nueva con fecha de inicio y fin, y mantienes la historia, y el informe del año pasado sigue siendo correcto.
El tipo 2 da más trabajo y es el que quieres cuando alguien pregunta "cuánto vendimos en Madrid en 2023".
Cómo llega el dato allí
ETL contra ELT. ETL es el orden clásico: extrae, transforma fuera, carga listo. Tenía sentido cuando el destino era caro y limitado.
ELT lo invierte: extrae, carga crudo, y transforma dentro del destino usando su potencia. Es el estándar hoy, y la ventaja práctica es grande: si la regla de transformación estaba mal, reprocesas a partir del dato crudo que ya está allí, sin extraer otra vez del origen.
Batch contra streaming. El batch procesa en ventanas: cada hora, cada día. Simple, barato, fácil de reprocesar. El streaming procesa evento a evento, con latencia de segundos, y es mucho más caro en complejidad: evento retrasado, ventana de tiempo, estado.
La pregunta correcta antes de elegir streaming: ¿alguien va a tomar una decisión distinta por saberlo ahora en vez de dentro de una hora? La mayoría de las veces, no.
CDC (captura de cambios de datos) es como el dato sale de la base transaccional hoy. En vez de un "select todo" cada noche (que es pesado, pierde borrados y pierde estados intermedios), lees el log de replicación de la propia base. Recibes cada insert, update y delete como un evento.
El cuidado con CDC en Postgres: el slot de replicación. Si el consumidor se para, la base retiene el WAL para él, y el disco se llena. Ya ha tumbado muchas bases de producción. Monitoriza el retraso del slot.
Warehouse, lake y lakehouse
Warehouse: estructurado y gobernado, con esquema definido en la escritura. Óptimo para consumo, rígido para datos nuevos.
Lake: archivo crudo en almacenamiento barato, con esquema en la lectura. Flexible, y se convierte en pantano si nadie lo gobierna.
Lakehouse: la síntesis. Archivos abiertos en el almacenamiento barato más una capa de metadatos (Iceberg, Delta, Hudi) que trae transacciones, viaje en el tiempo y evolución de esquema.
Hoy, para empezar desde cero, es el estándar que yo elegiría.
Y la organización en capas: bronce es el crudo, exactamente como llegó, inmutable: es tu red de seguridad para reprocesar. Plata es limpio, tipado, deduplicado. Oro es agregado y listo para el negocio.
Parece burocracia hasta el día en que una regla sale mal. Ahí te salva la semana, porque reprocesas desde el bronce.
Confianza en el dato
La forma más común de que un pipeline se rompa no es un bug: es que alguien del equipo de la aplicación renombre una columna sin saber que diez paneles dependían de ella.
El contrato de datos es el acuerdo explícito entre quien produce y quien consume: esquema, significado de cada campo, garantías de frescura y volumen, y el proceso de cambio. Con contrato, romperlo se convierte en una violación detectable en el pipeline del productor, y no en una sorpresa el viernes.
La prueba de datos es distinta de la prueba de código: pruebas el dato que pasó, no la función:
→ Esquema: ¿están las columnas y los tipos?
→ Volumen: ¿el número de filas de hoy está en el rango esperado?
→ Distribución: ¿media y nulos parecidos a los de ayer?
→ Regla de negocio: nada negativo, nada en el futuro, las claves cuadran.
La frescura es la métrica más importante y la más olvidada: ¿cuándo se actualizó esa tabla por última vez? Un dato viejo servido como actual es peor que un dato ausente, porque el ausente lo nota todo el mundo.
La idempotencia es la propiedad que separa un pipeline profesional de uno artesanal: ejecutarlo dos veces da el mismo resultado. La técnica estándar es sobrescribir por partición: en vez de insertar, reescribes entera la partición de aquel día. Reprocesar se vuelve trivial, y vas a reprocesar muchas más veces de las que imaginas.
Evento, partición y la métrica única
Si eres desarrollador de aplicación, tu mayor contribución al equipo de datos es emitir buenos
eventos: nombre en pasado (PedidoConfirmado, no ConfirmarPedido), identificador único para
deduplicación, el instante en que ocurrió separado del de procesamiento, versión del esquema, y los
datos que describen el hecho, no referencias que van a cambiar después.
Y usa el patrón outbox, para que el evento y la grabación sean atómicos.
El particionamiento en el lado analítico: los archivos quedan en carpetas por fecha, y la consulta que filtra por fecha lee solo esas carpetas. Eso es poda de particiones, y es la diferencia entre barrer dos gigabytes y dos terabytes, lo que en la nube es la diferencia entre céntimos y cientos de euros en la misma consulta.
Cuidado con el extremo opuesto: particionar por algo de alta cardinalidad genera millones de archivos minúsculos, y ahí el coste pasa a ser abrir archivos. El objetivo es archivos de algunos cientos de megabytes.
Y el problema más político: ¿cuál es la facturación del mes? Marketing tiene un número, finanzas tiene otro. Ninguno está mal. Lo definieron distinto: con o sin impuestos, con o sin cancelaciones, en la fecha del pedido o del pago.
La solución es una capa semántica: la métrica se define una vez, en código, versionada, y todo el mundo consume de ahí. La herramienta ayuda; lo esencial es que alguien sea dueño de la definición.
Contra el hype
Para la mayoría de las empresas, el stack correcto es: un warehouse gestionado, dbt para transformación en SQL versionado, un orquestador simple y un BI. Punto.
No necesitas Kafka, Spark y data mesh para treinta gigabytes de datos. Treinta gigabytes caben cómodamente en un DuckDB en tu portátil, y responden en segundos.
Data mesh, específicamente, es un modelo organizativo: dominios siendo dueños de sus propios datos como producto. Sin el cambio organizativo, adoptar las herramientas solo distribuye el lío.
Lee esto después
- IA AplicadaPaso 22IA en producción: RAG, eval y prompt injectionTodo el mundo consigue montar una demo que impresiona. Lo que separa la demo del producto son tres disciplinas, y la mayoría de los equipos no tiene ninguna de las tres.Leer artículo
- IngenieríaPaso 20Legado: caracterizar, coser y estrangularTres técnicas que permiten tocar con seguridad un sistema que no escribiste, no entiendes, y no puedes parar.Leer artículo
- IngenieríaPaso 19Pruebas que valen lo que cuestanLa prueba no existe para demostrar que el código está bien. Existe para que puedas cambiarlo mañana sin miedo. Ese cambio de objetivo lo reorganiza todo.Leer artículo