Capitulo 03
ETL: el Patron, no la Herramienta
Por que hablar con soltura de extract-transform-load importa mas que memorizar Informatica o SSIS
El patron ETL/ELT, idempotencia, cargas incrementales, manejo de errores en pipelines y el panorama de herramientas del mercado.
Lo que tienen en comun ofertas con AWS Athena, SQL Server + SSIS y BigQuery no es la herramienta — es el patron. Si entendes el patron, aprender la herramienta especifica de cada empresa es cuestion de dias.
3.1 El patron: Extract, Transform, Load
ETL (Extract, Transform, Load)
M13Patron de integracion de datos en tres pasos: extraer de una o mas fuentes, transformar (limpiar, tipar, aplicar reglas de negocio, deduplicar) y cargar en un destino de consumo (data warehouse, datamart, tabla de BI).
| Concepto | Descripcion |
|---|---|
| E | Leer datos de la fuente: una base de datos, una API, archivos planos (CSV, JSON, Excel). El reto tipico: fuentes con formatos y calidad inconsistentes. |
| T | Limpieza (nulos, duplicados), tipado correcto, aplicar reglas de negocio, unir con otras fuentes. Aqui vive la mayor parte del trabajo real de un Data Engineer/Analyst. |
| L | Escribir el resultado en el destino: una tabla de un data warehouse, un datamart, un archivo consumido por BI. Full load (reemplaza todo) vs incremental (solo lo nuevo). |
La alternativa naive es un unico script que lee, transforma y escribe todo junto — funciona hasta que algo falla a la mitad, y ahi no sabes si el problema fue de lectura, de una regla de negocio mal aplicada, o de la escritura. Separar Extract/Transform/Load en pasos identificables (aunque sea con funciones distintas en el mismo script) te permite loguear y reintentar cada paso de forma independiente, y reemplazar uno sin tocar los otros dos (ej. cambiar la fuente de un CSV a una API sin tocar la logica de transformacion).
Un escenario tipico de retail (Falabella, Crossing Hurdles en la muestra de mercado): cada sucursal exporta un CSV de ventas diarias a una carpeta compartida. El Extract lee todos los CSV del dia, el Transform normaliza formatos de fecha/moneda distintos entre sucursales y elimina duplicados (una venta reportada dos veces por un reintento del POS), y el Load consolida todo en una tabla central que alimenta el dashboard ejecutivo del dia siguiente.
3.2 ETL vs ELT: por que el cloud cambio el orden
ETL vs ELT
M13ELT invierte el orden: carga los datos crudos primero en el destino, y transforma DESPUES usando el poder de computo del propio data warehouse (BigQuery, Snowflake). Es el patron dominante en arquitecturas cloud modernas.
Antes, transformar datos fuera de la base (en un servidor ETL dedicado) tenia sentido porque la base no tenia capacidad de computo sobrante. Hoy, BigQuery y Snowflake escalan el computo bajo demanda — entonces tiene mas sentido cargar los datos crudos y transformarlos con SQL dentro del warehouse (herramientas como dbt formalizan este patron).
El patron “BigQuery + Sheets + Looker Studio” que aparece en la muestra de mercado (LATAM Airlines) es ELT por definicion: los datos crudos de operaciones se cargan directo a BigQuery, y las transformaciones (agregaciones, joins, calculos) se escriben como vistas SQL dentro del mismo BigQuery, consumidas despues por Looker Studio. No existe un servidor ETL intermedio — todo el computo de transformacion vive en el warehouse.
3.3 Idempotencia: la propiedad que evita desastres
Idempotencia
M13Propiedad de un proceso que produce el mismo resultado final sin efectos secundarios adicionales, sin importar cuantas veces se ejecute con la misma entrada. Un pipeline no idempotente que se reintenta tras un fallo puede duplicar datos.
-- MAL: si este INSERT corre dos veces (ej. por un retry automatico), duplica todas las filas
INSERT INTO ventas_consolidadas
SELECT * FROM ventas_raw WHERE fecha = '2026-07-24';
-- BIEN: MERGE (o "upsert") es idempotente — correrlo N veces da el mismo resultado
MERGE INTO ventas_consolidadas AS destino
USING (SELECT * FROM ventas_raw WHERE fecha = '2026-07-24') AS origen
ON destino.id = origen.id
WHEN MATCHED THEN UPDATE SET monto = origen.monto
WHEN NOT MATCHED THEN INSERT (id, fecha, monto) VALUES (origen.id, origen.fecha, origen.monto); La alternativa naive (un simple INSERT que asume que el pipeline siempre corre exactamente una vez) funciona perfecto hasta el primer fallo de red, timeout, o reintento automatico de un orquestador — momento en el que silenciosamente duplica datos y nadie lo nota hasta que el reporte financiero no cuadra. Diseñar con MERGE/upsert desde el principio cuesta poco mas de escribir y evita ese tipo de bug, que ademas es dificil de detectar despues (los datos duplicados parecen datos validos).
En un pipeline orquestado con Airflow, si una tarea falla por un timeout de red a mitad de la carga, el orquestador la reintenta automaticamente. Si esa tarea usa INSERT simple, el reintento duplica las filas que ya se habian cargado antes del timeout. Con MERGE, el reintento simplemente vuelve a aplicar el mismo resultado — sin duplicados, sin intervencion manual.
3.4 Full load vs carga incremental
Carga Incremental
M13Estrategia que procesa solo los datos nuevos o modificados desde la ultima ejecucion (usando una marca de tiempo o un ID), en vez de recargar la tabla completa (full load) cada vez.
Un full load es simple pero costoso a escala; una carga incremental requiere llevar registro de “hasta donde se proceso” (un watermark), pero escala a volumenes grandes sin reprocesar todo el historico.
No toda tabla necesita carga incremental. Una tabla de dimension pequeña (ej. dim_sucursal con 50 filas) es mas simple de mantener con full load diario — el costo de reprocesar 50 filas es insignificante, y evitas la complejidad de manejar un watermark para una tabla que casi no cambia. La carga incremental se justifica cuando el volumen (millones de filas) hace que reprocesar todo sea costoso en tiempo o dinero — tipicamente la tabla de hechos, no las dimensiones.
3.5 Manejo de errores y logging
Un pipeline de produccion nunca debe tumbarse completo porque una fila tiene un dato malformado. El patron estandar: mover las filas problematicas a una tabla/archivo de “cuarentena” (dead-letter), loguear el error con contexto suficiente para depurar despues, y continuar procesando el resto.
3.6 Orquestacion: scheduling y dependencias
A nivel conceptual, cuando un pipeline tiene varios pasos con dependencias (extraer → transformar → cargar → notificar), se necesita un orquestador que sepa el orden, reintente pasos fallidos, y alerte si algo no corrio. Airflow es la referencia mas comun de la industria para esto.
3.7 El panorama de herramientas (para reconocer, no necesariamente dominar)
| Concepto | Descripcion |
|---|---|
| Informatica/Talend/Pentaho | Herramientas con interfaz grafica de arrastrar y soltar para definir flujos ETL, comunes en empresas grandes con stacks legacy. Aparecen en ofertas de banca/retail con stacks Microsoft/Oracle. |
| SSIS/SSAS/SSRS | SQL Server Integration/Analysis/Reporting Services: el ecosistema ETL+BI de Microsoft. Comun en empresas con SQL Server como base principal. |
| dbt | Herramienta moderna que formaliza el "T" del ELT como SQL versionado en Git, con tests y documentacion. Estandar de facto en stacks cloud-native modernos. |
| Airflow | Define pipelines como codigo (DAGs en Python), con scheduling, reintentos y monitoreo. El orquestador mas mencionado en ofertas de Data Engineering. |
3.8 Recursos
3.9 Preguntas de entrevista
Q: ¿Que harias si un pipeline ETL falla a mitad de camino, despues de haber cargado el 60% de las filas?
Depende de si el proceso es idempotente. Si lo es (usa MERGE/upsert), simplemente lo vuelvo a correr completo sin riesgo de duplicados. Si no lo es, necesito o bien un mecanismo de checkpoint (retomar desde donde fallo) o revertir la carga parcial antes de reintentar. La leccion de fondo: diseñar el pipeline para que sea seguro reintentarlo desde el principio es mejor que optimizar prematuramente con checkpoints complejos.
🪤 Responder solo 'lo vuelvo a correr' sin mencionar el riesgo de duplicados si el proceso no es idempotente.- Elige un CSV publico con datos que se actualizan periodicamente (ej. un dataset de precios o clima).
- Escribi un script que extraiga, limpie/tipe, y cargue los datos en una tabla SQLite local.
- Usa un patron de upsert (INSERT OR REPLACE en SQLite) para que correr el script dos veces no duplique filas.
- Agrega manejo de errores: si una fila tiene un dato invalido, que se registre en un log y el proceso continue.