
================================================================================
GUÍA DAX STUDIO: DETECTAR CALLBACKDATAID EN DIRECTQUERY
================================================================================

Esta guía te permite identificar cuándo el Formula Engine (FE) está iterando
fila a fila y generando múltiples consultas SQL contra SQL Server.

================================================================================
PASO 1: CONECTAR DAX STUDIO AL MODELO
================================================================================

1. Abre Power BI Desktop con tu archivo PBIX cargado
2. Abre DAX Studio (descarga desde daxstudio.org)
3. En la ventana de conexión, selecciona:
      "Power BI / SSDT Model" → Elige tu archivo abierto
4. Haz clic en "Connect"

================================================================================
PASO 2: ACTIVAR SERVER TIMINGS Y QUERY PLAN
================================================================================

En la barra de herramientas de DAX Studio, activa:

   [✓] Server Timings
   [✓] Query Plan

Esto capturará:
   - Tiempo en Formula Engine (FE)
   - Tiempo en Storage Engine (SE)
   - Número de CallbackDataID
   - Consultas SQL generadas (en DirectQuery)

================================================================================
PASO 3: OBTENER LA CONSULTA DAX DESDE PERFORMANCE ANALYZER
================================================================================

1. En Power BI Desktop: Vista → Performance Analyzer → Iniciar grabación
2. Interactúa con un visual que uses una medida MAL (ej. "Total Sales SUMX")
3. Detén la grabación
4. Expande el visual lento y haz clic en "Copy query"
5. Pega la consulta en DAX Studio (pestaña principal)

================================================================================
PASO 4: EJECUTAR Y ANALIZAR RESULTADOS
================================================================================

Haz clic en "Run" (F5) en DAX Studio.

--- PESTAÑA "Server Timings" ---

Busca estas métricas:

   FE Time (ms)      → Tiempo del Formula Engine. Si es >50% del total, hay iteración.
   SE Time (ms)      → Tiempo del Storage Engine (SQL Server en DirectQuery).
   CallbackDataID    → Número de callbacks. En DirectQuery, cada uno = 1 subconsulta SQL.
   SQL Queries       → Número de consultas SQL generadas. Ideal: 1-2 por medida.

INTERPRETACIÓN:

   CallbackDataID = 0, SQL Queries = 1-2     → ✅ ÓPTIMO. Todo empujado a SQL.
   CallbackDataID = 5-20, SQL Queries = 5-20  → ⚠️ ALTO RIESGO. Iteración detectada.
   CallbackDataID > 50, SQL Queries > 50      → 🔴 CRÍTICO. Scan fila a fila.

--- PESTAÑA "Query Plan" ---

Busca nodos con estas etiquetas:

   CallbackDataID              → El FE solicita datos al SE fila a fila
   VertiPaq SE Query           → Consulta al Storage Engine
   DirectQuery-1, DirectQuery-2... → Consultas SQL individuales en DirectQuery
   Spool_Iterator              → Materialización intermedia (consume memoria)
   CrossApply                  → Producto cartesiano (muy peligroso)

Si ves "CallbackDataID" repetido muchas veces en el plan, tienes un iterador
sobre una tabla grande que debería reescribirse.

================================================================================
PASO 5: COMPARAR MEDIDA MAL vs. MEDIDA BIEN
================================================================================

Ejecuta la medida MAL y anota:
   - FE Time: _____ ms
   - SE Time: _____ ms
   - CallbackDataID: _____
   - SQL Queries: _____

Ejecuta la medida BIEN y anota:
   - FE Time: _____ ms
   - SE Time: _____ ms
   - CallbackDataID: _____
   - SQL Queries: _____

RESULTADO ESPERADO (con 3M filas):

   Medida MAL (SUMX sobre hechos):
      FE Time: 3,000-15,000 ms
      SE Time: 500-2,000 ms
      CallbackDataID: 50-500+
      SQL Queries: 50-500+

   Medida BIEN (SUM directo):
      FE Time: 0-50 ms
      SE Time: 200-800 ms
      CallbackDataID: 0
      SQL Queries: 1-2

================================================================================
PASO 6: VER LA CONSULTA SQL NATIVA
================================================================================

En DAX Studio, con una medida ejecutada:

1. Ve a la pestaña "Server Timings"
2. Expande el nodo "DirectQuery"
3. Haz clic derecho en cualquier "SQL Query" → "Copy SQL"
4. Pega en SSMS y ejecuta con "Include Actual Execution Plan" (Ctrl+M)

Esto te muestra EXACTAMENTE qué está ejecutando SQL Server y si está usando
índices o haciendo Table Scans.

================================================================================
PASO 7: USAR "VIEW NATIVE QUERY" EN POWER BI
================================================================================

Alternativa rápida sin DAX Studio:

1. En Power BI Desktop, crea una tabla con una sola medida MAL
2. Ve a la vista de datos (tabla)
3. Haz clic derecho en cualquier celda → "View Native Query"
4. Se abre una ventana con el SQL generado

Si la opción está deshabilitada (gris), significa que Power BI NO consiguió
traducir la medida a SQL nativo → el FE hará todo el trabajo = MUY LENTO.

================================================================================
CHECKLIST DE DIAGNÓSTICO
================================================================================

[ ] DAX Studio conectado al modelo Power BI
[ ] Server Timings activado
[ ] Query Plan activado
[ ] Performance Analyzer grabó interacción lenta
[ ] Consulta DAX copiada y ejecutada en DAX Studio
[ ] CallbackDataID contado (objetivo: 0-5)
[ ] SQL Queries contadas (objetivo: 1-3 por medida)
[ ] FE Time < 20% del tiempo total
[ ] Consulta SQL nativa revisada en SSMS
[ ] Medida BIEN comparada con medida MAL

================================================================================
EJEMPLO REAL DE SALIDA DAX STUDIO (DirectQuery)
================================================================================

--- MEDIDA MAL: SUMX sobre FactSales ---

Query Plan (resumen):
   AddColumns: <Total Sales SUMX>
      SUMX: <Expr0>
         CallbackDataID: <Qty * UnitPrice>   ← 3,000,000 veces
            VertiPaq SE Query: SELECT Qty, UnitPrice FROM FactSales

Server Timings:
   FE Time: 12,450 ms  (92%)
   SE Time: 1,080 ms   (8%)
   CallbackDataID: 3,000,000
   SQL Queries: 3,000,001

--- MEDIDA BIEN: SUM directo ---

Query Plan (resumen):
   AddColumns: <Total Sales SUM>
      SUM: <Amount>
         VertiPaq SE Query: SELECT SUM(Amount) FROM FactSales

Server Timings:
   FE Time: 12 ms      (1%)
   SE Time: 890 ms     (99%)
   CallbackDataID: 0
   SQL Queries: 1

================================================================================
