Bucle DWH: Modelos lógicos y físicos, Parte 1

Loop es mi proyecto personal, un sandbox donde construir experimentos con ciclos de iteración rápidos. Para aprender material nuevo necesito ejemplos reales y práctica. Si leo sobre tercera forma normal, lo mejor para entenderlo es revisar tablas físicas. Un proyecto personal es mi laboratorio para probar ideas iniciales y validar conceptos aplicados al trabajo real.

En este proyecto he decidido crear un pequeño data warehouse destinado al aprendizaje. La idea fue sencilla: uso relojes Garmin y registro tiempo dedicado al trabajo, proyectos personales, aprendizaje y juegos. Vamos a recolectar, modelar y transformar esos datos desde cero y luego construir dashboards con Metabase para responder preguntas como cuánto tiempo dedico por día, semana o mes a trabajar, aprender o jugar, cuántos entrenamientos tuve, cuándo empecé a entrenar por primera vez, y cuál es mi consistencia. También quiero calcular tiempos medianos y promedios de dormir y despertar por semana o mes.

Stack técnico utilizado: S3 y Postgres para capas raw y detallada, Apache Spark para transformaciones, delta.io para la capa de staging, Dagster para orquestación y Metabase para visualización. Si tu empresa necesita soluciones profesionales como aplicaciones a medida o software a medida puedes consultar nuestro servicio de desarrollo de aplicaciones y software a medida en Q2BSTUDIO.

Fuentes de datos: EARLY (antes Timeular) para time tracking y dispositivos Garmin Forerunner 265 para workouts, sueño y pasos. EARLY ofrece API y vende un cubo físico para tracking si se desea retroalimentación física. Para Garmin uso la librería garminconnect en Python. Para consumir EARLY implemento un cliente HTTP con validación pydantic.

Qué descargamos desde EARLY: carpetas, actividades, etiquetas y entradas de tiempo. Desde Garmin nos interesa inicialmente workouts y sleep. El objetivo es mantener un modelo lógico claro antes de implementar físicamente las tablas.

Modelo lógico: me apoyé en conceptos de diseño de bases de datos y en lecturas sobre modelado minimalista. El modelo lógico debe ser la única fuente de verdad del DWH. Extraemos anchors, atributos y links.

Anchors principales y su origen: Time Folder con id ejemplo 280326 (tabla física time_folder, origen EARLY), Time Activity id ejemplo 2052354 (time_activity, EARLY), Time Tag id ejemplo 14831771 (time_tag, EARLY), Time Entry id ejemplo 106227041 (time_entry, EARLY), Workout Type id ejemplo 21 (workout_type, Garmin), Workout id ejemplo 20150174780 (workout, Garmin), Sleep id ejemplo 1752277343000 (sleep, Garmin).

Atributos mínimos por anchor (tipo lógico y columna física): para time_folder nombre y descripción como TEXT not null; para time_activity nombre, status y descripción; para time_tag label; para time_entry start_at y end_at como TIMESTAMPTZ not null; para workout_type nombre; para workout start_at y end_at TIMESTAMPTZ not null; para sleep start_at y end_at TIMESTAMPTZ not null. Algunos nombres de columna ejemplo son time_folder.name, time_activity.status, time_entry.start_at, workout.start_at, sleep.end_at.

Links y cardinalidades: Time Folder a Time Activity 1 a N (time_activity.time_folder_id), Time Folder a Time Tag 1 a N (time_tag.time_folder_id), Time Activity a Time Entry 1 a N (time_entry.time_activity_id), Time Entry a Time Tag N a N mediante tabla link_time_entry__time_tag, Workout Type a Workout 1 a N (workout.workout_type_id).

Diagrama físico ERD: utilicé d2 para visualizar las tablas y las relaciones con notación Crows foot. En el diseño físico incluí claves foráneas, aunque posteriormente relajaremos esa dependencia por motivos operativos. La razón es simple: si recargamos una tabla de carpetas truncando y fallara la carga, las tablas dependientes quedarían vacías. Para evitar fallos por transacciones distribuidas se puede optar por cargas idempotentes y resolver referencialidad en procesos posteriores.

Notas sobre carga y consistencia: en proyectos reales y en DWH para empresas que ofrecen servicios cloud aws y azure o soluciones de inteligencia de negocio conviene diseñar capas claros raw, staging y curated. Aquí prefiero primero capturar datos tal cual y luego aplicar limpieza y joins en transformaciones orquestadas con Dagster y Spark. Ese enfoque facilita auditoría y reejecución de pipelines.

Relación con servicios profesionales: en Q2BSTUDIO combinamos experiencia en desarrollo de software, servicios cloud aws y azure, ciberseguridad, inteligencia artificial y business intelligence. Podemos integrar fuentes como dispositivos wearable, APIs de tracking y formularios para mood tracking, y convertir esos datos en paneles accionables con Power BI o Metabase. Si buscas implementar soluciones de inteligencia artificial o ia para empresas conoce nuestros trabajos en servicios de inteligencia artificial.

Casos de uso futuros: correlacionar métricas Garmin con horas de trabajo, añadir Google Forms para seguimiento de estado de ánimo y hábitos, o crear agentes IA que sugieran acciones basadas en patrones de sueño y productividad. Palabras clave que representamos en nuestros servicios: aplicaciones a medida, software a medida, inteligencia artificial, ciberseguridad, servicios cloud aws y azure, servicios inteligencia de negocio, ia para empresas, agentes IA y power bi.

Resumen rápido: exploramos fuentes EARLY y Garmin, diseñamos un modelo lógico con anchors, atributos y links, y creamos un diseño físico con ERD. En la siguiente entrega explicaré las capas del DWH y la ingestión de datos crudos, la orquestación de pipelines y ejemplos de transformaciones con Spark y delta.io. Si quieres que tu proyecto escale desde prototipo a solución productiva contamos con capacidades para llevarlo a producción, incluyendo auditoría, seguridad y visualización avanzada.

Sobre Q2BSTUDIO: somos una empresa de desarrollo de software y aplicaciones a medida, especialistas en inteligencia artificial, ciberseguridad, servicios cloud y business intelligence. Diseñamos soluciones a la medida de cada cliente para obtener insights accionables y soluciones seguras y escalables.