🎯 Situación
Hace unas semanas estaba revisando un reporte de Power BI que tardaba entre 8 y 12 segundos en cargar cada visual. El modelo de datos era razonable — no perfecto, pero no era el problema. El problema era el DAX.
IF anidados dentro de un SUMX que iteraba sobre 2 millones de filas. Columnas calculadas haciendo lo que deberían hacer las medidas. FILTER materializando tablas dentro de CALCULATE. Todo corregible. Todos patrones que veo en casi todos los proyectos que heredo.
Aquí están los 10 errores más frecuentes — y exactamente cómo corregirlos.
⚠️ El reto
La mayoría de las personas que aprenden Power BI vienen de Excel. Es un buen punto de partida — y un modelo mental peligroso para DAX.
📄 Fórmulas Excel
- Se evalúan celda por celda
- De izquierda a derecha, de arriba a abajo
- Inmediatas, familiares, predecibles
- Los IF anidados son práctica estándar
- El rendimiento rara vez es una preocupación a pequeña escala
⚡ Medidas DAX
- Se evalúan en un contexto de filtro
- Ejecutadas por dos motores distintos (storage + formula)
- El rendimiento depende de cómo el motor puede optimizar
- La iteración es costosa — evitarla cuando sea posible
- La estructura y el nombrado importan tanto como la lógica
No se trata de evitar DAX — se trata de entender cómo funciona realmente. Estos 10 patrones cubren el 80% del camino.
🔍 Los 10 errores
Cada error incluye un antes, un después y la razón por la que importa. Algunos son mejoras de legibilidad. Otros son ganancias de rendimiento importantes. Todos valen la pena corregir.
#1 — IF anidados al infinito → usar SWITCH
IF([Score] = "A", 1,
IF([Score] = "B", 2,
IF([Score] = "C", 3, 0)
)
)
SWITCH([Score],
"A", 1,
"B", 2,
"C", 3,
0 -- default
)
- Más legible y fácil de extender
- Más rápido: SWITCH hace cortocircuito al encontrar la coincidencia
- Agregar un caso no requiere anidamiento adicional
#2 — ISBLANK en todas partes → usar COALESCE
IF(ISBLANK([Revenue]), 0, [Revenue])
COALESCE([Revenue], 0)
- La mitad de caracteres, mismo resultado
- Maneja tanto BLANK como NULL
- Estándar moderno en DAX — úsalo de forma consistente
#3 — Repetir cálculos → usar VAR
IF(
[Revenue] - [Cost] > 0,
([Revenue] - [Cost]) / [Revenue],
0
)
VAR Profit = [Revenue] - [Cost]
RETURN
IF(
Profit > 0,
DIVIDE(Profit, [Revenue]),
0
)
- Cada expresión se evalúa una sola vez
- Legible como código limpio, no como fórmula
- Fácil de depurar: evaluar VAR por VAR
#4 — División clásica → usar DIVIDE
[Profit] / [Revenue]
DIVIDE([Profit], [Revenue])
- Maneja automáticamente las divisiones por cero (retorna BLANK por defecto)
- Evita errores silenciosos en los visuales
- Acepta un tercer argumento opcional como valor de retorno
#5 — FILTER innecesario dentro de CALCULATE
CALCULATE(
SUM(Sales[Amount]),
FILTER(Sales, Sales[Region] = "Canada")
)
CALCULATE(
SUM(Sales[Amount]),
Sales[Region] = "Canada"
)
- FILTER materializa una tabla completa — costoso a gran escala
- El predicado directo es optimizado por el motor VertiPaq
- Uno de los ajustes de rendimiento más impactantes en DAX
#6 — COUNTROWS(FILTER(…)) → usar CALCULATE
COUNTROWS(
FILTER(Sales, Sales[Status] = "Won")
)
CALCULATE(
COUNTROWS(Sales),
Sales[Status] = "Won"
)
- FILTER itera cada fila antes de contar
- CALCULATE empuja el filtro al motor de almacenamiento
- Mismo resultado — mucho más rápido en tablas grandes
#7 — SUMX innecesario → usar SUM
SUMX(Sales, Sales[Amount])
SUM(Sales[Amount])
- SUMX itera fila por fila (formula engine)
- SUM corre en el storage engine — mucho más rápido
- Reservar SUMX para expresiones a nivel de fila: SUMX(Sales, Sales[Qty] * Sales[Price])
#8 — Columnas calculadas para agregaciones dinámicas
-- Calculated column (wrong approach)
Margin % = Sales[Profit] / Sales[Revenue]
-- DAX measure (correct approach)
Margin % = DIVIDE(SUM(Sales[Profit]), SUM(Sales[Revenue]))
- Las columnas se calculan en el refresh y se almacenan en memoria
- Las medidas se calculan en tiempo de consulta — siempre sensibles al contexto
- Una medida se adapta automáticamente a cada slicer, filtro y visual
#9 — ALL en la tabla de hechos — demasiado amplio
CALCULATE([Revenue], ALL(Sales))
CALCULATE([Revenue], ALL(DimDate))
- ALL(Sales) elimina todos los filtros sobre la tabla de hechos — rara vez es lo que se quiere
- Apuntar a una dimensión específica es preciso y predecible
- Caso de uso frecuente: % del total ignorando solo el filtro de fecha
#10 — Una medida de 30 líneas sin estructura
-- Everything inline, nothing named
[Revenue] - [Cost] / ([Revenue] - [Cost] + [Overhead])
VAR TotalRevenue = SUM(Sales[Revenue])
VAR TotalCost = SUM(Sales[Cost])
VAR Overhead = [OverheadMeasure]
VAR NetProfit = TotalRevenue - TotalCost - Overhead
RETURN
DIVIDE(NetProfit, TotalRevenue)
- Depurable: comentar RETURN y reemplazarlo por un nombre de VAR
- Auto-documentado: los nombres de variables explican la lógica
- Reutilizable: extraer cualquier VAR como medida base
✓️ Los 3 palancas reales
Corregir errores DAX uno por uno es útil. Pero si quieres entender por qué algunos reportes son rápidos y otros lentos, solo hay tres cosas que importan:
- Modelado primero (80% del problema) — un star schema, relaciones correctas y tablas de dimensiones limpias resuelven la mayoría de los problemas de rendimiento antes de escribir una sola línea de DAX
- DAX optimizado después — evitar la iteración (SUMX, FILTER) donde la agregación (SUM, CALCULATE) puede hacer el trabajo; usar VAR para eliminar evaluaciones repetidas
- Reducir cardinalidad e iteración al final — columnas de alta cardinalidad en tablas de hechos, anidamiento innecesario de CALCULATE y DIVIDE faltantes son los cuellos de botella restantes
💡 Síntesis
No hace falta memorizar los 10 de golpe. Empieza por los que aplican a tu reporte actual y corrígelos uno por uno. Las ganancias se acumulan.
Las tres correcciones con mejor relación esfuerzo/resultado:
- Reemplazar FILTER por predicados directos en CALCULATE — ganancia de rendimiento inmediata en cualquier tabla grande
- Pasar a VAR + RETURN en cualquier medida con expresiones repetidas — legibilidad y rendimiento en un solo movimiento
- Reemplazar SUMX por SUM donde no hay expresión a nivel de fila — te obliga a pensar en cuándo la iteración es realmente necesaria
DAX recompensa la estructura. Cuanto más intencional eres en lo que escribes — y por qué — más rápidos y mantenibles se vuelven tus reportes.
👉 Un reporte lento en Power BI casi nunca es un problema de Power BI.
Es un problema de DAX. Y los problemas de DAX tienen patrones.