Existen en la industria buenas prácticas , tips y patrones de diseño comprobadas a lo largo del tiempo y con muchos casos de éxito , pero de igual forma existen malas practicas, errores y acciones a evitar cuando se aborda la tarea de diseñar un modelo de datos para apoyar a la toma de decisiones .
Dentro de estos errores , es muy común el que se presenta en este articulo y también se presentará el método recomendado para manejarlo. Ojo, las ideas propuestas acá(y por los expertos de la industria) entran en conflicto con las buenas prácticas de diseño de modelos de datos que se enseñan religiosamente en universidades y cursos de bases de datos, por lo cual se recomienda terminar de leer el post antes de dejarlo a medias pensando que lo que en el se dice es incorrecto.
El error es: modelar estructuras y jerarquías normalizadas.
A lo largo de mi experiencia me he encontrado con este error en múltiples ocasiones ,incluso siendo realizado por arquitectos de datos experimentados , pero a que se debe? Principalmente a que como se menciono , esta práctica se evangeliza y se trata religiosamente en universidades y cursos de bases de datos y comúnmente los arquitectos de datos incursionan en el diseño de un modelo de datos de toma de decisiones sin tener en cuenta las diferencias(incluso sin un entrenamiento adecuado) en el enfoque y objetivos de un modelo de datos transaccional(comúnmente relacional) y un modelo analítico(toma de decisiones, descubrimiento de patrones y conocimiento).
En un modelo transaccional , el modelo se realiza pensando en objetivos tales como: captura de información,reducción de redundancia, integridad referencial , disminución de espacio de almacenamiento y para esto se recurre comúnmente a un modelo entidad/ relación normalizado, en el cual se modelan entidades del mundo(o negocio) y las relaciones entre las mismas.
Por otra parte en un modelo analítico , el diseño se realiza con objetivos tales como: consumo de información,toma de decisiones, análisis de indicadores del negocio, facilidad de consumo y entendimiento por parte de usuarios no técnicos, velocidad de acceso a la información ,aplicar pocos o ningún calculo y formulas durante el consumo(durante el query, y hacerlo en el ETL) y que el query sea lo mas "limpio" posible y es acá donde entra en conflicto el enfoque analítico con el transaccional ,ya que en el modelo analítico no se modelan entidades y sus relaciones, si no procesos de negocio, las métricas generadas por el proceso y el contexto o puntos de vista de análisis del proceso y sus métricas(dimensiones) .En este caso es permitido y altamente RECOMENDADO el tener estructuras de datos redundantes , no normalizadas y sacrificar la disminución de espacio de almacenamiento .
Entonces entrando en materia(y es acá donde los arquitectos de sistemas y datos encontraran difícil de digerir y aceptar el material) y viendo ejemplos reales del error y su solución , manejaremos 2 situaciones comunes :
- Modelado de productos y categorías.
- Modelado de información geográfica(en este ejemplo estado y ciudad)
- Enfoque transaccional: En este enfoque se modelan entidades y sus relaciones,para el primer caso identificando 2 entidades : producto y categoría y la relación entre ambas(un producto pertenece a una categoría y en una categoría se agrupan muchos productos).. Para el segundo caso se identifican 2 entidades: estado y ciudad y la relación entre ambas(una ciudad pertenece a un estado, un estado contiene muchas ciudades). Para ambos casos esta es una relación de jerarquía , a nivel físico este diseño implicaría 2 tablas por jerarquía y una llave foránea como relación entre las mismas.A continuación se presenta un modelo ER simplificado(se ha dejado de lado otras entidades y otros atributos de las entidades mostradas con fines de ejemplo)
- Enfoque analítico(dimensional): En este enfoque se modelan procesos de negocio, las métricas generadas por los mismos, y el contexto(descripción,puntos de vista) llamado dimensión en el que se generan las métricas. Para estos 2 ejemplos en vez de 4 entidades(2 para información de producto y 2 para información geográfica) se tienen únicamente 2 dimensiones(seleccionando siempre el nivel mas granular o mas bajo en la jerarquía) , y cada dimensión contiene toda la información de la jerarquía representada , para estos 2 ejemplos , tendríamos que la dimensión de producto, tiene como atributo la categoría del mismo, y la dimensión de ciudad tiene como atributo el estado al que pertenece,esto genera redundancia y rompe reglas de normalizacion ya que para este ejemplo la categoría se repetiría muchas veces(1 por cada producto en la categoría),pero como se mencionó esto es permitido y recomendado con fines de generar simplicidad de consumo(query fácil de construir) y tiempos de respuesta mas ágiles(query eficiente) ya que ni la base de datos, ni el usuario final debe realizar costosas uniones innecesarias(joins) entre múltiples tablas en la jerarquía. Algo que viene a la mente al arquitecto de datos acostumbrado a modelar de manera relacional , es que esto también genera un mayor costo en disco pero se deben tomar 2 cosas en cuenta:
- El mayor costo de disco es permitido y es el precio a pagar por la simplicidad y tiempo de consumo de datos.
- Comúnmente los modelos analíticos son implementados sobre bases de datos columnares(como Amazon Redshift o SAP Sybase IQ), diseñadas con este tipo de modelado en mente y utilizando internamente estructuras como bitmaps(o indices bitmap) para almacenar una única vez cada valor diferente de la columna y acceder al valor a través del bitmap,logrando así una compresión significativa. Crear un modelo normalizado(y jerarquías con múltiples tablas) en un motor columnar, es desperdiciar y desaprovechar las capacidades(Y la alta inversión económica!) y enfoque del mismo.
Esta recomendación no es algo generado por mi persona, lo recomiendan los expertos de la industria(incluso los creadores del modelado dimensional) como podemos ver en las siguientes referencias. Espero que esto sea de utilidad para generar mejores modelos analíticos.
Ver mistake #1
Ver rule#6
O bien, en el libro "The data warehouse toolkit", capitulo 8 ,pagina 398 ver : Mistake #8
Autor: Luis Leal
Excelente artículo, solo tengo una pregunta. ¿Qué pasa cuando tenemos que utilizar esos campos en los where? ¿No es más lento comparar varchar qué int?
ResponderEliminarSaludos.
Gracias por tu comentario y por tu pregunta , en efecto es mas lento comparar cadenas que enteros, pero hay varias cosas que debemos tomar en cuenta:
Eliminar- El join es una de las operaciones mas costosas en la base de datos y en el escenario que mencionas , si le damos valores ficticios para ejemplificar imaginemos que el join tiene un costo de 1000 y la comparacion de cadenas 800(sobre digamos un 600 del int), con cada join que evitamos generar estamos teniendo una pequeña ganancia.
- Por lo general , estos campos de cadena son datos descriptivos o catálogos(en el modelo multidimensional serian una dimensión) que por lo general tienen una cardinalidad(o numero total de valores) baja, y que muy recomendadamente debieran ser indexados ,en algunos motores de bases de datos(principalmente columnares) existen indices tipo "bitmap" o "dictionary" en los que internamente si se guarda un valor numerico representndo a la cadena, lo cual elimina el costo que mencionas.
-Y por ultimo, lamentablemente la mayoria de herramientas o suites de inteligencia de negocios que generan el codigo SQL en funcion de capas semanticas pre-configuradas , no hacen el mapeo entre llaves numericas y cadenas cuando el usuario final hace filtrado de datos, por lo cual ese costo siempre estaria presente y si siempre estara presente y no podemos evitarlo, mas vale evitar otros tipos de costos como el de un join.
Te invito a leer nuestros otros posts y enviarnos tus sugerencias o dudas!
Saludos