martes, 20 de julio de 2021

Power Pivot: ADDCOLUMNS vs SELECTCOLUMNS

Hoy toca un poco de DAX para Power Pivot para Excel.
En concreto vamos a comparar el rendimiento de dos funciones similares: ADDCOLUMNS y SELECTCOLUMNS:
La primera obviamente agrega columnas calculadas a una tabla en sí, o también a una expresión de tabla dada:
ADDCOLUMNS(table; name; expression;[; name; expression]…)
Con esta función obtendremos por tanto una nueva tabla con todas sus columnas originales y las nuevas agregadas.


Mientras la segunda devuelve una tabla solo con columnas existentes y seleccionadas de una tabla, o bien con nuevas columnas generadas 'artificialmente' con DAX:
SELECTCOLUMNS(table; name; scalar_expression [; name; scalar_expression]…)
Además debemos saber que esta función nos devuelve una tabla con el mismo número de filas que la tabla original; sabiendo que cada expresión se evalúa en el contexto de una fila a partir de esa tabla original especificada.

A priori, ambas tienen muchos aspectos en común.. y de hecho se emplean indistintamente... aunque en estos puntos comentados reside su pequeña diferencia; ¿el rendimiento de una y otra no pueden ser igual, ya que una trabaja sobre la totalidad de las tablas, mientras que la otra solo sobre las columnas seleccionadas!!??.
Imagina un caso extremo. Tenemos una tabla con 2.000.000 de registros y 1.000 columnas.
¿Cuál piensas que sería el tiempo necesario de procesamiento para realizar un cálculo simple empleando una y otra función??... Uno que necesita trabajar sobre todas esas columnas aunque no se utilicen en el cálculo?, u otro que solo opera sobre 2-3 columnas, que son las estrictamente necesarias??.

Pongamos un ejemplo y trabajemos brevemente sobre este y comprobemos tiempos de ejecución.
Partimos de dos tablas:
1- Tabla de ventas ('TblVENTAS') con 600.000 registros y 15 columnas.
2- Tabla de precios ('TblPRECIOS') con 9 registros y 2 columnas.

Power Pivot: ADDCOLUMNS vs SELECTCOLUMNS
Cargamos ambas al modelo de datos y las relacionamos por el campo Artículo-Producto:
Power Pivot: ADDCOLUMNS vs SELECTCOLUMNS

Crearemos ahora dos medidas que acumulen para cada cliente solo los tres importes más altos.
Así en el área de cálculo de la TblVENTAS incorporamos:
fxSELECTCOLUMNS:=VAR DosCols=SELECTCOLUMNS(TblVENTAS;
		"Customer";TblVENTAS[Cliente];
		"Total Sales €"; CALCULATE(SUMX(TblVENTAS;TblVENTAS[Unidades]*RELATED(TblPRECIOS[Precio Unitario])))) 
RETURN
SUMX(TOPN(3; DosCols;[Total Sales €];DESC);[Total Sales €])


fxADDCOLUMNS:=VAR N_Cols=ADDCOLUMNS(TblVENTAS;
			"Total Sales €"; CALCULATE(SUMX(TblVENTAS;TblVENTAS[Unidades]*RELATED(TblPRECIOS[Precio Unitario])))) 
RETURN
SUMX(TOPN(3; N_Cols;[Total Sales €];DESC);[Total Sales €])


La primera medida 'fxSELECTCOLUMNS':
fxSELECTCOLUMNS:=VAR DosCols=SELECTCOLUMNS(TblVENTAS;
		"Customer";TblVENTAS[Cliente];
		"Total Sales €"; CALCULATE(SUMX(TblVENTAS;TblVENTAS[Unidades]*RELATED(TblPRECIOS[Precio Unitario])))) 
RETURN
SUMX(TOPN(3; DosCols;[Total Sales €];DESC);[Total Sales €])

selecciona la columna 'Cliente' renombrándola como 'Customer',
y por otro lado incorpora una nueva columna calculada 'Total Sales €'.

De forma similar la segunda medida 'fxADDCOLUMNS':
fxADDCOLUMNS:=VAR N_Cols=ADDCOLUMNS(TblVENTAS;
			"Total Sales €"; CALCULATE(SUMX(TblVENTAS;TblVENTAS[Unidades]*RELATED(TblPRECIOS[Precio Unitario])))) 
RETURN
SUMX(TOPN(3; N_Cols;[Total Sales €];DESC);[Total Sales €])

añade a la tabla de ventas (con todas sus columnas) una nueva...

Nada especial a priori... Para controlar los tiempos de ejecución de ambas medidas nos iremos a DAX Studio (https://daxstudio.org/) y ejecutaremos ambas medidas, comparando los milisegundos de cada una de ellas.
En otro momento explicaré el cómo... de momento me quedaré con unos pantallazos de resultados:
Power Pivot: ADDCOLUMNS vs SELECTCOLUMNS
Comprobamos que las diferencias son mínimas entre ambas medidas!!!
Podríamos pensar que las diferencias es por que nuestra tabla tiene pocas columnas, pero realizando el mismo ejercicio con 200 columnas, los resultados son equiparables y prácticamente idénticos!! :O

Es decir, en las medidas propuestas parece tener más relevancia el cálculo evaluado que la elección de la función.

Donde aparecen verdaderamente las diferencias entre una y otra función es cuando devolvemos el conjunto de columnas, esto es, si sobre un origen de 200 columnas y 200.000 registros, generamos estas queries:
fxSELECTCOLUMNS:=VAR DosCols=SELECTCOLUMNS(TblVENTAS;
		"Customer";TblVENTAS[Cliente];
		"Total Sales €"; CALCULATE(SUMX(TblVENTAS;TblVENTAS[Unidades]*RELATED(TblPRECIOS[Precio Unitario])))) 
RETURN
DosCols


fxADDCOLUMNS:=VAR N_Cols=ADDCOLUMNS(TblVENTAS;
			"Total Sales €"; CALCULATE(SUMX(TblVENTAS;TblVENTAS[Unidades]*RELATED(TblPRECIOS[Precio Unitario])))) 
RETURN
N_Cols

En ambos casos se crean dos tablas... pero en el caso de SELECTCOLUMNS una tabla de dos columnas... y en el caso de ADDCOLUMNS una tabla de 201 columnas. Nota la diferencia abismal entre tiempos:
Power Pivot: ADDCOLUMNS vs SELECTCOLUMNS

167.730 ms versus 3.563 ms
Increible!!, pero esperado. ADDCOLUMNS queda destrozado frente a SELECTCOLUMNS

Reflexión y conclusión personal: Cuando el origen tenga un número elevado de columnas, siempre mejor trabajar con SELECTCOLUMNS...
cuando haya un número 'pequeño' de columnas, es el proceso de evaluación o cálculos añadidos los que aportan tiempo de proceso... y no hay aparente diferencia entre una y otra.
Asi pues, diría en base a esto... usemos siempre SELECTCOLUMNS, cuando no necesitemos el resto de columnas ;-)

No hay comentarios:

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.