¿Qué va en una dimensión?

30 06 2008

image

Varias veces me ha ocurrido que al trabajar con un data warehouse me encuentro con que en la dimensión producto viene todo lo imaginariamente posible. Por ejemplo, si estamos hablando que si la información viene de un sistema de dulcería, en el catálogo de productos vienen todos los productos vendibles en ella: paletas, dulces, refrescos, palomitas o rosetas de maíz, chocolates, etc.

… pero también vienen escobas, el detergente para lavar los pisos, el aceite para el maíz inflado, los vasos desechables y hasta el papel higiénico del baño.

¿Qué sucede? Pues que el sistema sirve tanto para vender que como sistema de inventarios o almacén. Así que el catálogo de producto almacena todo.

Pregunta ¿entonces en un modelo de ventas de dulcería, la dimensión de productos deberá tener todos estos artículos aunque no se vendan?

Yo creo que nó.

Creo que lo correcto es crear 2 dimensiones: productos y materias primas. Los 2 se llenarán a partir del único catálogo de productos. Debemos extraer solo aquello que tiene que ver con ventas y depositarlo en el modelo de ventas. Lo otro irá al modelo de inventario o almacén.

Recuerden que a la información de un data warehouse o cubo «se le habrán aplicado procesos de transformación y limpieza».





Llaves surrogadas o sustitutas.

12 06 2008

image

Esta es una de las buenas prácticas que a mi juicio muchas veces se omiten en el diseño de un data warehouse. Las llaves surrogadas o sustitutas son una llave generada artificialmente y que viene a sustituir el campo llave de la dimensión.

Para ponerlo en bits y bytes, lo que hacemos es diseñamos la tabla de tal forma que la llave primara sea un campo con un tipo de dato entero y que además tenga la propiedad «autoincrement» ( o identity, o lo que sea, todo depende de la base de datos utilizada). En la tabla existe un campo que servirá para almacenar la llave original. Al llenar la tabla se generarán valores numéricos que usaremos en vez del campo clave original.

Las ventajas son muchas. Para mí la principal es mejorar el tiempo de respuesta de la base de datos ya que buscar entre números enteros es lo que menos trabajo le cuesta a la base de datos; pero también hay otras, por ejemplo, si estamos juntando en un data warehouse información de sistemas transaccionales diferentes y cada uno de ellos tienen llaves que no se parecen en nada la una de la otro, las llaves surrogadas o sustitutas nos permitirán tener una llave homogénea para ambos sistemas.

Nos permite también resolver cosas como por ejemplo mantener la historia en el tiempo y a la vez separarla. Por ejemplo si queremos que un vendedor que ahora pertenece a otra región, su historia se conserve en el data warehouse en la región original, lo que hacemos es crear un nuevo registro en la tabla de vendedores con una nueva llave sustituta para ese vendedor y usamos esa nueva llave para almacenar las ventas de ese cliente a partir de la fecha que el movimiento ocurre. De esta forma en el data warehouse tendremos las 2 cosas.

IdVendedor CveVendedor Vendedor Región
2345 A00X456 Miguel Gutierrez Norte
 
5467 A00X456 Miguel Gutierrez Centro

Si queremos la historia del vendedor podemos hacer la consulta por el # de Vendedor lo cual abarcará a las 2 llaves (la nueva y la antigua).

select sum(ventas)
from HechosVentas A
join DimVendedores B on a.idVendedor = b.IdVendedor
where b.CveVendedor = ‘A00X456’

Si queremos las ventas de cada región:

select region, sum(ventas)
from HechosVentas A
join DimVendedores B on a.idVendedor = b.IdVendedor
group by region

El modelo por sí solo lo resolverá.

Surrogadas

Por cierto, en el modelo arriba mostrado (que no tiene nada que ver con el ejemplo de regiones y vendedores que les daba) pueden ver que yo por ejemplo a todas las llaves usrrogadas las identifico por el sufijo «ID» y para los campos llaves originales reservo todos los campos con el sufijo «cve».

¿implica más trabajo? Si, así es. Muchas veces por falta de tiempo yo en mi caso las omito. También en cierto que hay diferentes maneras de generarlas por ejemplo con algún ETL. Los beneficios son muchos así que cada vez que diseñe un modelo, ponga en la balanza los beneficios que le pueda traer el incluir dichas llaves.

Por cierto, si vá a utilizar el «count distinct» estas llaves sustitutas les vienen como anillo al dedo.





Agregados exactos

9 04 2008

Hoy mientras hacía cubos (¿qué otra cosa?) y utilizaba unos indicadores compuestos avanzados del tipo:

SUM( CASE WHEN (COLOR = ‘RED’ AND TIPO = 3) THEN INVENTARIO_LT ELSE INVENTARIO + EXCEDENTES )

Constataba lo poderosos que son. Sin embargo este tipo de indicadores son muy complicados de mantener en un data warehouse. El problema viene cuando la base de datos ha crecido demasiado y tenemos que crear agregados (por Tienda o Departamento digamos), la herramienta OLAP no puede usar estos agregados debido a que las columnas que se ocupan para el CASE dentro del sum no existen en el agregado.

Para que los agregados funcionaran tendríamos que agregar a cada agregado las columnas Color y Tipo. La herramienta OLAP solamente usaría estos agregados cuando lo elementos del: group by+where+(lo que está dentro del sum), existen en el agregado. 

Hay que programar los dashboards para que al abrirlos utilicen todas las variables en el agregado. Tantito que el usuario juegue con el tablero, ya sea filtrando o moviendo una dimensión provocará que no use agregados. A este tipo de agregados que solamente se pueden usar cuando la consulta exactamente tiene las columnas del agregado les llamo agregados exactos.

Entiendase que normalmente no es así, por ejemplo una consulta que solo use un sum(ventas) puede obtener el total de ventas x tienda de un agregado a nivel tienda-departamento-producto.

Respecto a estos indicadores avanzados que usan agregados exactos, tendría que programar para cada variante  de la consulta que el usuario haga: un agregado. Me refiero con variante a cualquier filtro de dimensión que el usuario aplique o dimensión que mueva (que normalmente es lo que hacen los usuarios con una herramienta OLAP).

Lo mejor es traducir estos indicadores simples de tal forma que no se tengan que referenciar otras columnas (propiedades) de dimensiones dentro del sum.





Mejores ID para la tabla de Tiempo

2 04 2008

No se como escribir esto, a menudo mientras reviso un modelo estrella o un data warehouse me encuentro que al ejecutar:

select * from SalesFact

Un select para ver como está la tabla de hechos, el select que ejecuto muestra que la columna TimeId ( o como sea que la hayan llamado) trae valores como 54548,  54549,…54555. Esta columna es el campo por el que se hace join con la tabla de tiempo. A que fecha corresponden dichos números, ni idea. Habrá que hacerle un select a la tabla de tiempo y ver a que fecha corresponde el ID.

Lo mejor es no usar estos valores, es mucho más sencillo usar la fecha en formato yyyyMMdd. El resultado sigue siendo un número entero y mucho más fácil de leer

20080331 = 31 de Marzo del 2008

Para llenar la tabla de hechos no se requiere ir primero a la tabla de tiempo para ver que ID le toca a cada fecha, basta con un:

SQLServer: convert( varchar, fecha, 113)

Oracle: TO_CHAR( fecha, yyyyMMdd)

MySQL: Year(Fecha)*10000+Month(Fecha)*100+day(Fecha)

¿a poco nó?





Ceros y Nulos en un data warehouse

19 09 2007

Una de la grandes lecciones aprendidas una y otra vez, proyecto tras proyecto, es el uso correcto de ceros y nulos en el datawarehouse. El principio es sencillo e importante conocer:

5548+ nulo = nulo

No importa lo que pongas el resultado se anula. Una o dos veces al principio me ocurrió que llenaba los cubos o estrellas y al tratar de sacar el total de ventas con un

select sum( ventas ) from HechosComercial

obtenía como resultado nada. Se platica sencillo pero lo que en realidad ocurría era:

—¿cuánto tiempo falta para que termine la carga?
—una hora…
—¿a que horas es a la presentación a dirección?…tenemos que darle una revisada rápida a las pantallas
—dentro de 2 horas
—tiempo suficiente.

Una hora después…

— ya terminó la carga, a ver, revisa las pantallas.
— ¡las pantallas están vacías! No se cargó la información, %&/%#…¿falló algo?
— No, todo está bien. Los logs no marcan errores e incluso las tablas tienen información
Confused
— A lo mejor definiste mal los indicadores, revisa la definición
— …está todo bien
— ¿no será que usaste el indicador equivocado? hay que revisar las pantallas.
— …No, todo es correcto.
— ¿y si la haces de nuevo?
—…ya la hice de nuevo sigue igual..¿cuanto falta?
— 15 minutos…

Más tarde y después de cancelar la presentación o de haber arruinado el buen humor de la junta de resultados resulta que encontramos el query:

select sum( ventas ) from HechosComercial

— No entiendo, si ejecuto la consulta me regresa un nulo. Ya revisé cada uno de los totales por región. Saque el detalle, lo exporté a excel e hice los cálculos. Coinciden perfectamente.
—¿no será un bug de la base de datos?
—Yo creo que sí.
—Voy a buscar algo en google…

Así, después de horas y horas finalmente descubrimos que un registro con el valor de la columna ventas igual a nulo era el causante de todo. 2 millones 354 mil registros de información y un mendigo registro con el valor de nulo echa a perder todo.

A partir de entonces como procedimiento normal de la carga, sustituimos todos los nulos por un cero o en su defecto uso un desagradable sum( isnull( Ventas,0)). También en el create table en la definición de las columnas ponemos un default de cero.

Alguien pudiera pensar…»sencillo, en el where ponle Ventas is not null» pero con millones y millones de registros estoy seguro que sentaríamos el servidor al obligarlo a recorrer registro por registro toda la estrella para discriminar aquellos registros con nulos. No se les ocurra indexar las columnas-indicadores para acelerar la busqueda. Sería una barbaridad.

No siempre usamos cero, a veces en ciertos casos hemos tenido que dejar los nulos por algún requerimiento del indicador. Todo depende.

Al menos una vez al año recibimos alguna llamada de una persona desesperada por que las pantallas no muestran información y con un «pero las tablas si están llenas». Eso quiere decir que ocurre a menudo. ¿A alguien le ha pasado algo parecido?

Technorati tags:





Indicadores simples

6 09 2007

Siguiendo con las reflexiones del post anterior: Una sola verdad. Quería comentar que hay más beneficios de crear métricas simples en vez de un indicador monto con una dimensión donde venga el indicador.

Imaginese que tiene que hacer 50 reportes. Suponiendo que tiene un indicador Monto o Importe y una dimension que tiene como valores: Ventas, Devoluciones, Cancelaciones, Mermas, Pedidos y Notas de Crédito; y tiene que calcular un indicador Ventas Netas ( Ventas – Devoluciones – Cancelaciones ) y ese indicador lo tiene que usar en cada uno de los reportes ¿se puede imaginar la friega?.

Primero hay que calcular las Ventas Netas ¿ Los valores de Devoluciones vienen negativos o positivos? Si vienen positivos tendrá que hacer hacer algún truco para restarselo a las Ventas.

Suponiendo que esto no fuera un problema y ese calculo lo hace en los 50 reportes (por que normalmente se hacen el calculo cada vez en cada nuevo reporte); cuando al día siguiente le informen:

Para calcular las ventas netas además hay que restarle las Notas de crédito

Ya puedo imaginar la cara que hace At wits end. Tendrá que modificar cada uno de los 50 reportes uno por uno…

Si convierte las dimensiones a indicadores ( un indicador Ventas, un indicador Devoluciones, uno Cancelaciones y uno Notas de Crédito) puede crear un indicador lógico que sea Ventas Netas = Ventas – Devoluciones – Cancelaciones. Si al día siguiente le dicen que hay un cambio pues solo modifica la definición del indicador lógico y listo. ¡Todos los reportes funcionan! No hay que hacer nada.

Tome en cuenta que una vez que tenga los cubos o el data warehouse listo, lo que hará será hacer reportes y más reportes, pantallas y más pantallas, gráficas y más gráficas.

Así que vale la pena invertir tiempo en tener métricas simples.

 ¿…será que alguien en Alemania me lea? Praying

TIP: Para los que usen Analysis Services de Microsoft pueden usar la funcion Filter de MDX para convertir sin mucho esfuerzo una dimension a indicadores.

Technorati tags:





Uso de índices en un data warehouse

28 08 2007

mapa

Varias veces me ha pasado que al visitar un data warehouse me encuentro con que en las tablas hay cero índices. Tengo muy presente unos cubos que se tardaban 2 días en procesarse.

El uso de índices es uno de las cosas que más afecta el performance o desempeño. Debería ser obligado que todo data warehouse tenga los apropiados.

Para los que se preguntan ¿que es un índice? Una sencilla respuesta sería hacer una comparación. Para encontrar donde está ubicado un cliente que tengo que visitar tengo 2 opciones: buscar la dirección en un mapa o lanzarme a ciegas. Si me lanzo a ciegas tengo que recorrer calle por calle, preguntar e ir contando número por numero hasta dar con la dirección. Los 2 sabemos que éste último método es pésimo.

De 10 veces solo una vez encontré la dirección a la primera y eso que tuve mucha suerte.

Los índices son los mismo. Son un mapa de la información. Si no hay mapa entonces la base de datos recorre uno por uno los registros para dar con ellos. Un síntoma de que ocurre esto es que al pararse enfrente del servidor las lucecitas están prendidas y no se detienen.

Aparte de que el % de uso del procesador es elevado.

Si usted es de esos usuarios avanzados sabrá que se puede monitorear la cantidad de accesos a disco y que el resultado dice que están arriba de lo normal.

Algunas recomendaciones para usted y su data warehouse respecto a los índices:

  • indexar las primary keys de las tablas. Si, a veces hay primary keys y no hay índices. Sobre todo en los motores de bases de datos viejitos que no tenían tanta integridad.
  • Evitar usar campos llaves que no sean numéricos. Prefiera los campos enteros para las llaves. Eso hará que los índices se eficienten mucho y respondan de manera más rápida. Además esto le permitirá definir índices de tipo bitmap que funcionan hiper-eficientemente por no decir «hechos la @#&%!». Conozco una base de dato que cada índice mide el 25% de lo que mide la tabla. Con 2 o 3 índices ya nos acabamos el disco duro. Todo por que las llaves son varchar.
  • Indexar aquellas columnas por las que hará búsquedas frecuentemente.
  • Si tiene tiempo, paciencia y recursos pruebe lo que dice el manual de almacenar los índices en un archivo o disco diferente al de datos. Se sorprenderá al ver los tiempos de respuesta. Si todavía tiene paciencia entonces pruebe todo el concepto (datos, temporales, base de datos de sistema, indices y logs). Si tiene una base de datos gigantesta, los tiempos de respuesta están lentos y aún no ha probado esto…no entiendo como ha sobrevivido.
  • Lea los manuales y trate de entender los diferentes tipos de índices que su base de datos tiene, las desventajas y ventajas que tiene cada uno de ellos. El costo y los beneficios que le puede traer.
  • Si tiene Oracle el uso del paralelismo le puede traer muchos beneficios, investigue.
  • En algunas bases de datos los índices también se pueden particionar. Esto aplica para data warehouses gigantescos.
  • Un data warehouse está diseñado para consultas así que es perfectamente válido que esté sobre-indexado, pero no exagere.
  • Monitoree las consultas que se lanzan sobre la base de datos y verifique que usen índices. Si no usan índices investigue por qué. A lo mejor simple y sencillamente no tiene.
  • Pregunte qué están haciendo en otras empresas respecto a este tema y no tenga temor de contratar alguien que le apoye con este tema.

¿Ahora entiende por qué aquellos cubos que mencioné se tardaban 2 días en procesarse? Había cero índices.





Los mejores escenarios

14 08 2007

Tomando en cuenta el post anterior (léanlo si no lo han hecho) donde nos topamos con usuarios renuentes al cambio, usuarios que por inercia (la cual se ha llevado a todos entre las patas) siguen usando lo mismo de toda la vida; hay varias preguntas: ¿cómo podemos diseñar mejores reportes o escenarios?¿podemos sustituir esos reportes en papel por un tablero de control?¿Qué información debo de incluir en mis reportes o informes?¿es suficiente?

Reflexionemos. Cuando ese reporte Not worthy (que todos adoran) nació, pasó lo siguiente:

—Dime como quieres que sea el reporte—Sistemas le preguntó al usuario
Confused

Y ahí está el problema: El usuario sabe que lo que requiere es información acerca de los 5 mejores clientes, qué sucursales van mal, qué vendedores tienen problemas en su desempeño, qué productos no despegan; NÓ como quiere el reporte.

Vean que grave está esto. Al hacer así la pregunta, el usuario detectó que él (nó sistemas) tenía que diseñar un reporte de tal forma que la información que busca todos los días la pueda encontrar sin mucho esfuerzo. Así que puso columnas y mas columnas, totales, cálculos, % de participación todo en un solo reporte; de tal forma que cuando intentara localizar que vendedores tienen problemas en su desempeño tuviera toda la información a la mano.

¿Alguno de ustedes ha intentado localizar que vendedores están mal en un reporte con 24 columnas, 1200 renglones, 25 subtotales y 45 páginas? Háganlo, y comprenderán el esfuerzo que requiere.

Dicho todo lo anterior y regresando a la pregunta ¿cómo podemos hacer mejores reportes, tableros de contro o informes? Sencillo. NO pregunten como quieren que sean, pregunten:

¿Qué es lo que estás buscando?¿Dime que información necesitas para tomar decisiones?

Y si el usuario dice: Quiero ver qué vendedores y sucursales tienen problemas. Hágase entonces una pantalla donde vengan las sucursales y su venta; con la venta alarmada en rojo si la sucursal está mal. Y le dicen la usuario: cuando veas una sucursal en rojo quiere decir que tiene problemas, le das clic y te da la lista de los vendedores malos. Para cada vendedor te muestra lo que lleva vendido, cuanto debería llevar (el presupuesto) y lo que vendió el mes pasado.

Denle exactamente la información que está buscando el usuario. Nó lo hagan pensar ni buscar en un mar de información ya que ese no es el objetivo de la aplicación. El objetivo es tomar mejores decisiones.

Si hacen esto estoy seguro que tendrán éxito en su tablero de control o cuadro de mando ¿Me explico?

Technorati tags:





Automatizando estupideces

8 08 2007

Reportes1

Los proyectos que más odio son aquellos en donde todo está dicho.

Recuerdo con especial interés uno de ellos. Fue un cliente muy difícil. La prospección duró varios meses y nos evaluaron todo. Que si los tableros de control, que si los componentes, que si soportaba mapas o velocímetros, que si tenia alarmas, que si hacía dril-down, que si los cubos, que si las bases de datos, que si mil cosas mas.

Cuando pasó todo esta etapa de la venta y el proyecto inició me entregaron una carpeta bastante gruesa de reportes o informes. Eran cientos de ellos y con la consigna: «así los quiero».

Los reportes uno tras otro consistían en una tabla con “n” columnas y filtros arriba. Las columnas casi siempre eran las mismas: los meses del año, el YTD, el mes pasado, el presupuesto…en fin columnas más, columnas menos.

—Oye, pero podemos hacer cosas mucho mejores que esto
—NO, así los quiero
—pero son puras tablas…
—si, así los quiero. El objetivo es poder imprimir los reportes tal cual.

Y ahí esta. No se requiere un análisis, todo esta perfectamente definido. ¿El drill-down? ¿Los múltiples componentes? Bien, gracias.

Si insistes en preguntar obtienes la siguiente respuesta:

—Nuestro director es una persona importante, el maneja esos reportes a la perfección. Sabe donde esta cada dato y carga esa carpeta para todas partes y en cada viaje. No podemos modificar nada de ahí.

Pues a darle. A desarrollar cada uno de los reportes, columna por columna, cuidando la separación en pixeles de cada una, los encabezados, los títulos, el pie de página, el espacio del engargolado…y mil cosas más que dan un dolor de cabeza.

Pues listo, terminé los famosos reportes y a cuadrar los datos. En esa etapa pude trabajar hombro con hombro con el usuario. Cada vez que no cuadraba un numerito enfrente del usuario le hacía drill-down, lo graficaba, le sacaba tendencias y obtenía la diferencia. Al ver todo esto todo esto el usuario me preguntó que era todo eso, así que le hice una demo de la herramienta.

Quedó fascinado y a la vez pensativo. Viendo sus reportes se volteó y me dijo.

—Estás automatizando mis estupideces ¿verdad?
—la mera verdad, SI.

Y me platicó la historia de los famosos reportes. La primera versión de los reportes surgió cuando tenían COBOL y se imprimían en aquellas hojas verdes gigantescas. Como tuvieron que sustituir COBOL por otra cosa y las impresoras gigantes por las pequeñas pues contrataron a alguien que desarrollara en FOX aquellos reportes. Luego vendrían las bases de datos cliente servidor y las impresoras laser, así que contrataron a alguien que los desarrollara en Visual Basic y se imprimieran en Laser. Los reportes desde los 70’s no habían cambiado en nada y ahora era mi turno de hacerlos. Ellos tenían que cambiar la tecnología por otra mejor.

De esta plática como resultado muchos de los reportes se fueron a la basura y pude proponer algunos tableros. Hay mucho que aprender de esta anecdota.

Las reflexiones las dejaré para un post posterior.





Algunas recomendaciones para la tabla de hechos

26 07 2007

Cuando hagas tu tabla de hechos sigue estas recomendaciones.

  • No usar llaves compuestas. Trata de no usar llaves compuestas, esto es, utiliza un solo campo para hacer join con las otras tablas. Esto hará que la base de datos trabaje menos. Es un poco complejo de programar pero ayudará bastante en el performance de la base de datos. ¿ Y no funciona si uso llaves compuestas? Si, si funciona pero se nota una diferencia en los tiempos de respuesta. Esto se nota más si la tabla de hechos será gigantesca.
  • Define la Primary Key en la tabla de hechos. Si en el CREATE TABLE establecemos quién es la primary key, la base de datos creará un índice con la combinación de estos campos lo que hará más rápidas las búsquedas….Si, si me he topado con DWH que no tienen índices y que al procesar los cubos se tardaban 2 días. Si su tabla de hechos no tiene índices, pongale uno, el más apropiado de entrada es aquel que incluye a todos los campos que forman la llave de la tabla….Lo mismo aplica para las tablas de dimensiones o catálogos.
  • Utilice los tipos de datos apropiados. En el diagrama puede ver como el campo unit sales usa un tipo de dato DOUBLE PRECISION; esto estaría bien si nos dedicaramos a la venta de garbanzos 😀 y quisiéramos llevar la cuenta del # de garbanzos vendidos (no sé, pero un kilo de garbanzos ha de traer cientos de ellos ) ¡Es para almacenar números gigantescos!. Si lo que vendemos es maquinaria a lo mejor con un Decimal(10,2) estaría bien. Tenemos que acoplarnos al número que almacenará la columna. Espacio de más hará que la base de datos crezca más y se requiera más espacio, y a más espacio más trabajo y más servidor y más memoria y más…
  • Tenga cuidado con el tipo de dato entero. Una vez haciendo un cubo de recursos humanos teníamos 2 indicadores: # de Personas y #Personal Requerido. Como no se puede tener 1/2 persona ni requerir 1/2 persona los dos los definí de tipo entero. La bronca vino al hacer las consultas. Resulta que en las bases de datos, al dividir un entero entre otro entero el resultado es un entero, o sea ( 768/1000 ) = 1. Luego teníamos a cada rato que anteponerle CONVERT u otra instrucción por que el resultado o era 1 o 0. Recuerdo que esto aplica para SQLServer y Redbrick, no recuerdo en este momento si pasa lo mismo en Oracle.
  • Las tablas de hechos pueden tener campos de apoyo. Si, no siempre se tienen únicamente los hechos y dimensiones. Se pueden tener campos como Fecha de entrega, de compra, etc.
  • No guarde campos que se pueden calcular. Si por ejemplo tiene un indicador que es el precio promedio = ventas $/ Ventas Unidades; no haga el calculo y lo guarde en la tabla de hechos por que al consultar los datos deberá usar una formula de agregación como SUM, AVG, MAX, MIN y si lo analiza, la distorsión del indicador será bastante grande al promediar un precio promedio en millones de registros o pocos de ellos.
  • Use nombres amigables. No hay razón para no utilizar el nombre VENTAS UNIDADES para una columna en la tabla de hechos. Luego no tiene uno NPI de lo que hay en cada columna.

Recuerde, los datawarehouses se diseñan pensando en ser de fácil consulta. Son para analizar información.