52 apuntes vivos para el examen: la regla de oro que te hace acertar, la trampa clásica con la que te intentan despistar y la analogía kawaii para que se te quede. 🌸
IntermedioAvanzado
Filosofía: entender el porqué, no memorizar respuestas. Cada bloque trae la regla de oro (el truco para acertar), la trampa clásica (cómo te intentan despistar) y, cuando ayuda, una analogía kawaii para que se quede. 💜
Está organizado por los tres dominios oficiales del examen más los fundamentos transversales. Déjalo para el final, justo antes de presentarte, cuando ya domines los 17 módulos.
Streaming / telemetría / series temporales + KQL protagonista
Eventhouse
T-SQL de primera clase + escritura T-SQL + transacciones
Warehouse
Autoservicio ligero de Power BI, sin Spark
Datamart (casi siempre trampa)
🎯 Método: tacha cada requisito uno a uno sobre cada opción. Gana la que no falla ninguno, no la que "encaja con la palabra que más suena".
⚠️ Trampa: ver "KQL" y saltar a Eventhouse sin comprobar el resto. Si piden "escribe SOLO con Spark", el eventhouse falla (su escritura nativa es ingesta de eventos, no Spark) → gana Lakehouse (Spark escribe nativo; T-SQL vía SQL endpoint; KQL vía shortcut de OneLake).
🌸 Analogía: el lakehouse es la nevera familiar — cualquiera abre, mete o saca comida por la puerta que quiera (Spark, SQL, KQL). El eventhouse es la cinta de sushi giratoria 🍣: brilla con cosas que fluyen sin parar. El warehouse es la despensa ordenada con etiquetas (T-SQL, estructura, transacciones).
⚠️ Dataflow Gen2 NO soporta: windowing functions avanzadas, visualización exploratoria ni lógica muy compleja.
🌸 Analogía: elegir herramienta es como elegir utensilio de cocina 🍳. Para un corte rápido y sencillo, el pelador (dataflow). Para un plato elaborado con mil pasos, los cuchillos de chef (notebook). Para una receta con una técnica muy concreta de repostería (windowing), el molde especializado (T-SQL).
03Arquitectura medallion: herramienta por capa
Capa
Herramienta típica
Pista en el enunciado
Bronze (raw, sin transformar, solo formato)
Copy activity de pipeline
"no changes", "raw", "minimal effort", "built-in connection", "retry on error"
Silver (cleansing, dedup, calidad)
Notebook (PySpark)
"extensive cleansing", "deduplication", el equipo "prefers Python/SQL"
Gold (modelo dimensional, agregaciones)
Notebook o stored procedure (T-SQL)
según el destino (warehouse → SP)
🎯 La respuesta sale de cazar la frase exacta del requisito, no de qué herramienta prefieres. Bronze pide cero transformación → Copy activity (¡NO dataflow, que transforma!). Silver pide limpieza pesada → notebook.
⚠️ Trampa: poner Dataflow Gen2 en bronze. El dataflow es una herramienta de transformación (Power Query) → contradice el "no changes other than file format".
🌸 Analogía: es una fábrica de mermelada 🍓. Bronze = recibir la fruta tal cual llega del campo (solo la metes en cajas, no la tocas → Copy). Silver = lavar, quitar lo malo, cortar (cleansing → notebook). Gold = hacer la mermelada lista para vender (modelo final → SP/notebook).
04Modelado dimensional (star schema)
🎯 Reglas de oro:
Star schema = dimensiones denormalizadas (planas, una tabla por dimensión). "Minimize joins / development effort / analytical performance" → estrella ⭐
Snowflake = dimensiones normalizadas en varias tablas → más joins, más complejo.
Joining key = siempre surrogate key (identificador único generado por el sistema), nunca nombres ni fechas de negocio.
Va en la DIMENSIÓN
Va en la FACT TABLE
Clave de negocio (ProductID)
Claves foráneas (surrogate keys)
Atributos descriptivos (Name, Color)
Métricas (SalesAmount, Qty)
Surrogate key (PK generada)
Fechas de evento (transaction Date)
Columnas SCD (ValidFrom, ValidTo, IsCurrent)
IDs de evento (TransactionID)
⚠️ Trampa golosa: "denormalize into the FACT table" suena a denormalizar (bueno en estrella), pero mezclar dimensión con hechos = one-big-table, NO star schema. La denormalización correcta es dentro de la dimensión.
💡 Por qué surrogate key y no la business key del origen: aísla de los cambios del origen, soporta SCD (historial) y hace joins más eficientes (entero pequeño).
🌸 Analogía: pregúntate siempre "¿esto describe al producto o describe la venta?". Nombre/color/categoría describen el producto → dimensión. Importe/fecha/nº de pedido describen la venta → fact. Es como separar la ficha del personaje (dimensión) de lo que hace en cada partida (hechos). 🎮
05SCD: los 4 tipos (0, 1, 2, 3)
Qué hace cada tipo cuando un valor cambia (ejemplo: una clienta se muda de ciudad):
Tipo
Qué hace
Histórico
Firma
Type 0
ignora el cambio (inmutable)
ninguno
valores fijos (fecha de nacimiento)
Type 1
sobrescribe (pierde lo viejo)
ninguno
solo estado actual
Type 2
fila nueva (conserva versiones)
completo
ValidFrom / ValidTo / IsCurrent ⭐
Type 3
columna extra (valor anterior)
1 nivel
PreviousValue + CurrentValue
🎯 Identificar en el examen:
"histórico / at the time of / point-in-time / track over time" + columnas ValidFrom/ValidTo → Type 2.
"solo valor actual / overwrite / latest" → Type 1.
"valor actual Y anterior" (un nivel) → Type 3.
"nunca cambia / inmutable" → Type 0.
🌸 Analogía de los carnets de identidad 🪪: cada versión de la clienta es un carnet con fecha de emisión (ValidFrom) y caducidad (ValidTo). Type 2 guarda todos los carnets (histórico completo). Type 1 rompe el carnet viejo y solo tiene el actual. Type 3 guarda el carnet de ahora y el anterior (solo uno hacia atrás). Type 0 nunca cambia el carnet (es tu partida de nacimiento).
06Join a un SCD Type 2: histórico vs actual
Columnas de un SCD Type 2: valid_from (desde cuándo), valid_to (hasta cuándo) e is_current (¿es la versión de ahora? 1/0).
Quiero analizar...
Condición del join
Atributos HISTÓRICOS (como era en la fecha del pedido)
rango: OrderDate >= valid_from AND OrderDate < valid_to
Atributos ACTUALES (como es hoy)
is_current = 1
🎯 Regla: "historical / point-in-time / como era ENTONCES" → rango de fechas. "current / como es AHORA" → is_current = 1. El límite inferior es >= valid_from (inclusivo) y el superior < valid_to (exclusivo, para no solapar versiones).
🌸 Analogía: si preguntas "¿en qué ciudad vivía Ana cuando compró en 2022?" → miras qué carnet estaba vigente en 2022 (rango de fechas = histórico). Si preguntas "¿dónde vive Ana hoy?" → coges el carnet vigente (is_current = 1 = actual). 🪪
07Hash functions para detectar cambios
Un hash es una "huella dactilar" de una fila: convierte todas las columnas en un código corto. Si CUALQUIER dato cambia → el hash cambia por completo.
🎯 Uso: detectar cambios en tablas anchas (muchas columnas) de forma eficiente. En vez de comparar 100 columnas × millones de filas, comparas un solo hash por fila.
Método
Coste
Hash function (huella de la fila)
⚡ bajo — 1 comparación por fila
Comparación directa (columna a columna)
🐌 alto — N comparaciones por fila
💡 Regla: "detectar cambios + muchas columnas + minimize resources" → hash function sobre los datos entrantes (source). Implementación real: HASHBYTES('SHA2_256', ...) en T-SQL o sha2() en PySpark. También se llama "row hash" o "checksum column".
🌸 Analogía: comparar dos fichas de 100 campos a mano es agotador 😵. Pero si a cada ficha le pones una pegatina con un código único que cambia si cambias cualquier campo, solo comparas las pegatinas: ¿distintas? → algo cambió. Rápido y limpio. 🏷️
🛡️
Dominio 1 · Implementar y gestionar (30-35%)
08Roles de workspace y least privilege
Rol
Puede...
Viewer
Ver items y leer datos vía SQL endpoint. El más bajo.
Contributor
Crear/editar items, ejecutar pipelines, escribir. El "trabajador".
Member
Todo lo de Contributor + compartir y gestionar acceso.
Admin
Control total del workspace.
🎯 Regla de oro (¡patrón que cae fijo!): cuando el enunciado dice "you already assigned object-level / item permissions"+"least privilege" → la respuesta es casi siempre Viewer, porque la escritura ya está cubierta por otra vía (object-level) y el rol de workspace solo tiene que aportar la visibilidad.
⚠️ Trampa: ves "update the tables" y saltas a un rol con escritura (Contributor). Pero si la escritura ya está concedida por object-level permissions, solo necesitas el rol mínimo que dé "ver items" = Viewer. Los permisos se SUMAN (rol de workspace + permisos de objeto).
💡 Lección transversal: lee dos veces las frases que parecen de relleno ("you already assigned..."). Suelen resolver medio requisito y cambiar la respuesta.
09Sharing de Lakehouse y permisos
Quiero que...
Permiso al compartir
Lea tablas por SQL
Read all SQL endpoint data (ReadData)
Lea ficheros por Spark/OneLake
Read all Apache Spark (ReadAll)
Construya informes de Power BI
Build reports on the default semantic model
NO vea otros items del workspace
NO asignar rol de workspace → solo sharing directo
🎯 Reglas de oro:
"SQL sí, Spark no" → Read all SQL endpoint datasola (sin ReadAll). ReadData da las tablas por T-SQL pero NO los ficheros.
"Que no vea el resto del workspace" → sharing directo del item, cero roles de workspace.
⚠️ Trampa: dar un rol de workspace (Viewer/Member) además del sharing. El rol da acceso a TODOS los items del workspace → viola el "que no acceda a otros items". El sharing de item da acceso SOLO a ese item.
10Roles de dominio y gobierno
Rol
Alcance
Fabric admin
Todo el tenant. Crea dominios y nombra a los domain admins.
Domain admin
Gestiona su dominio: subdominios, asignar/quitar workspaces, configuración, nombrar contributors.
Domain contributor
Solo asigna sus propios workspaces a dominios existentes. No crea nada.
⚠️ Ambigüedad conocida: técnicamente, crear el PRIMER dominio es exclusivo del Fabric admin. Pero si el enunciado añade "least privilege", se espera domain admin (asume que un Fabric admin ya creó el contenedor y delegó). Si la pregunta fuera aislada "Who can create a domain?" → ahí sí, Fabric admin.
💡 Señal luminosa: la coletilla "principle of least privilege" casi nunca lleva al rol más poderoso. Elige el permiso más ajustado que aún cumpla la tarea.
11Dominios: la herencia que no existe
🎯 Regla de oro: pertenecer a un dominio NUNCA da un rol de workspace. Son planos separados:
Dominio = gobierno (organización lógica, sensitivity labels, catálogo).
Roles de workspace = acceso real (Viewer/Contributor/Member/Admin).
Nadie "hereda" acceso a un workspace por estar en el mismo dominio o grupo → hay que asignar el rol explícitamente.
⚠️ Trampa del "default domain" + orden temporal: te haces domain contributor automáticamente solo de los workspaces que el mecanismo del default domain ASIGNA. Si un workspace ya tenía dominio (ej. lo creó su domain admin) ANTES de añadir tu grupo al default domain → el default domain respeta esa asignación y NO lo reasigna → NO ganas domain contributor sobre él.
Escenario
¿WS asignado vía el default mechanism?
¿Grupo = domain contributor?
WS creado ANTES de añadir el grupo al default
❌ No (se preserva la asignación previa)
❌ No
WS creado DESPUÉS de añadir el grupo al default
✅ Sí
✅ Sí
🌸 Analogía del imán 🧲: el default domain es un imán que recoge canicas (workspaces) sueltas por el suelo y les pone tu pegatina de "domain contributor". Si una canica ya estaba guardada en la caja de otro dominio antes de activar el imán, el imán no la recoge (respeta que ya está guardada) → esa canica no lleva tu pegatina.
🎯 CONCEPTO CRÍTICO: los roles de workspace Admin/Member/Contributor BYPASEAN la seguridad de OneLake (RLS/CLS/table-level). Si un usuario necesita escribir en un lakehouse (requiere Contributor o superior), automáticamente puede leer TODO ese lakehouse, incluida cualquier PII.
⚠️ Por eso "escribir en la tabla A sin leer la tabla B (PII) en el mismo lakehouse" es imposible con permisos granulares. La solución es separar físicamente la PII:
Crear un nuevo workspace + lakehouse.
Migrar la tabla de PII allí.
Dar Contributor en el workspace original (ya sin PII).
💡 Nota del mundo real: "migrar la tabla" en el examen es un paso conceptual; en la práctica es un notebook/pipeline/CLI, y el deployment pipeline NO copia datos. El examen abstrae el "cómo".
🌸 Analogía: darle a alguien la llave para escribir en el cuarto (Contributor) es darle la llave maestra del cuarto entero — verá TODO lo que hay dentro, también la caja fuerte con datos sensibles. Si quieres que use el cuarto pero no toque la caja fuerte, la única forma es sacar la caja fuerte a otro cuarto (separar la PII). 🔐
13Row-Level Security (RLS)
El RLS en Fabric Warehouse son dos piezas: una inline table-valued function (TVF) (el predicado) + un CREATE SECURITY POLICY que la aplica.
-- 1️⃣ LA FUNCIÓN (predicado): inline TVF
CREATE FUNCTION dbo.tvf_rlspredicate(@Author AS varchar(50))
RETURNS TABLE
WITH SCHEMABINDING -- ← palabra clave tras WITH (NO "inline")
AS
RETURN SELECT 1 AS resultado
WHERE @Author = USER_NAME() -- ← compara con el usuario actual
GO
-- 2️⃣ LA POLÍTICA (aplica el filtro):
CREATE SECURITY POLICY RLSFilter
ADD FILTER PREDICATE Security.tvf_rlspredicate(AuthorEmail) -- la columna aquí
ON AuthorSales -- ← solo la TABLA, no tabla.columna
WITH (STATE = ON) -- ON = activa la política
🎯 Piezas clave:
Si piden UN objeto imprescindible → FUNCTION.
Tras RETURNS TABLE → WITH SCHEMABINDING (no INLINE; inline es el tipo de función, no una keyword).
El predicado usa USER_NAME() para identificar al usuario.
En el ON de la policy → solo el nombre de la tabla.
⚠️ Trampa: el SCHEMA (Security) aparece en todos los tutoriales, pero es solo buena práctica organizativa, no obligatorio.
💡 Bonus: en Direct Lake, si hay RLS en el SQL endpoint, Power BI hace fallback a DirectQuery.
🌸 Analogía: la función es el portero con la lista ("¿tu nombre está en la fila? entonces pasas"), y la security policy es contratar a ese portero para una puerta concreta (la tabla). Sin portero no hay control; sin contratarlo para la puerta, no hace nada. 🚪
14Column-Level Security (CLS)
Oculta columnas enteras (da error si las pides, no las ves).
GRANT SELECT ON tabla(col1, col2, col3) TO [usuario@dominio.com];
-- Las columnas OMITIDAS de la lista quedan ocultas
🎯 Reglas de oro:
Permiso de lectura = SELECT (nunca "READ").
Usuario = email de Entra entre corchetes[user@contoso.com].
Ocultar una columna = omitirla de la lista.
💡 CLS vs DDM: el CLS oculta (error si la pides); el DDM enmascara (la ves con XXXX). "Prevent accessing" → CLS. "Ver parcial/enmascarado" → DDM.
🌸 Analogía: el CLS es tachar columnas con tinta negra opaca — esa columna no existe para ti. El DDM es poner una pegatina de XXXX encima — sabes que hay algo, pero no lo lees. 🖍️
15Dynamic Data Masking (DDM)
Enmascara los datos sensibles (los ves con XXXX, no se ocultan).
ALTER TABLE dbo.tabla
ALTER COLUMN columna
ADD MASKED WITH (FUNCTION = 'partial(2,"XXXXXXXXX",4)');
🎯 Sintaxis fija: ALTER TABLE ... ALTER COLUMN ... ADD MASKED WITH FUNCTION (siempre ALTER + ALTER).
Función
Qué hace
default()
enmascara todo
email()
aXXX@XXXX.com
random(a,b)
número aleatorio
partial(prefix,"pad",suffix)
X del inicio + relleno + Y del final
⚠️ "Ver los primeros X y los últimos Y" → partial(X, "...", Y). "READ" y "REPLACE" NO son funciones válidas.
💡 El Viewer lo ve enmascarado; Admin/Member/Contributor o quien tenga UNMASK ven los datos reales.
🌸 Analogía: el DDM es el número de tu tarjeta en el recibo del súper: **** **** **** 1234. Ves los últimos 4 (partial), el resto está tapado, pero la tarjeta sigue ahí. 💳
SOLO items con datos: lakehouse, semantic model, warehouse
Cannot be endorsed
—
Dashboards de Power BI (no admiten ningún badge)
🎯 Trucos:
El item es un dashboard → respuesta casi segura "Cannot be endorsed".
"core / single source of truth" + lakehouse/semantic model → Master data.
"meets organizational standards" → Certified. "ready for sharing and reuse" → Promoted.
⚠️ Trampa: un dashboard "executive-level" te tienta hacia Certified/Master data, pero los dashboards no admiten ningún badge.
🌸 Analogía: son los sellos de calidad de la mermelada 🍓. Promoted = "casera, recién hecha" (la pone quien cocina). Certified = "aprobada por sanidad" (un revisor oficial). Master data = "denominación de origen" (la fuente auténtica, solo para productos con sustancia = items con datos). El dashboard es el escaparate, no un producto → no lleva sello.
17Deployment pipelines: qué se despliega y qué no
Concepto
¿Se despliega?
Metadata de los items (tablas, medidas, relaciones)
✅ Sí
Datos de los semantic models
❌ No (solo metadata)
Scheduled refresh (el horario)
❌ No (configuración operativa del destino)
Incremental refresh policy (definida en el .pbix)
✅ Sí
Dataflows Gen1
❌ No soportados (solo Gen2)
Items de Real-Time Intelligence (Eventhouse, Eventstream, KQL DB...)
✅ Sí (nativos)
🎯 Regla de oro: los deployment pipelines despliegan metadata y contenido, NUNCA datos ni triggers operativos (schedules).
⚠️ Trampa doble de "policy": el scheduled refresh NO se despliega; la incremental refresh policy SÍ se despliega.
🔧 Nota del mundo real: el botón Compare puede marcar un dataflow como "Different" si tocaste su programación en un stage — es la metadata del item marcada como modificada (y el compare de dataflows da falsos positivos famosos). Eso NO significa que el schedule viaje al desplegar.
🌸 Analogía: el deployment pipeline es una fotocopiadora de planos 📐. Copia el diseño de la casa (metadata), pero NO los muebles de dentro (datos) ni la hora a la que riegas el jardín (schedule). Eso lo pones tú en cada casa nueva.
Si ves "PAT" en una pregunta de Azure DevOps → señuelo (el PAT es de GitHub).
Solo un workspace Admin conecta a Git.
🌸 Analogía: GitHub te pide una llave física que tú fabricas (el PAT) y la dirección del portal (URL). Azure DevOps te reconoce por tu cara (OAuth, ya estás logueada) y solo necesita saber a qué edificio/piso/puerta ir (org/project/repo/branch). 🔑
19Identidades y autenticación
Identidad
Para qué
Service principal
Automatización externa contra las APIs de Fabric (CI/CD, scripts, Azure DevOps → Fabric).
Managed identity
Como el SPN pero sin gestionar secretos, para recursos que viven en Azure.
Workspace identity
Fabric autenticándose contra Azure (trusted workspace access, shortcuts a ADLS con firewall).
User (Entra) + password
Trabajo interactivo de personas. Nunca para automatización.
🎯 Truco — pregúntate "¿quién llama a quién?":
Algo externo llama a Fabric (Azure DevOps ejecuta un deployment pipeline vía API) → service principal.
Fabric necesita acceder a un recurso de Azure protegido → workspace identity.
⚠️ Trampa: "workspace identity" suena moderno y tentador, pero va en dirección Fabric→Azure. Para DevOps→Fabric API es service principal. "Username and password" para CI/CD es casi siempre el señuelo.
🌸 Analogía: el service principal es un robot con su propio carnet que llama a la puerta de Fabric. La workspace identity es el carnet de Fabric para salir a buscar cosas a Azure. Un usuario con contraseña es una persona llamando a la puerta (no sirve para tareas automáticas que corren de madrugada). 🤖
🎯 Regla de oro: "Azure resource + public access disabled + Spark job/notebook" → managed private endpoint. "on-premises SQL Server + gateway + copy data" → pipeline (Copy activity).
⚠️ Trampas:
Integration runtime y data management gateway son de ADF/Synapse, NO de Fabric (señuelos). "Data management gateway" es el nombre deprecado del on-premises data gateway.
Spark (notebook / SJD) NO puede usar el on-premises data gateway. En cuanto veas "gateway on-prem", descarta notebook/Spark job.
💡 Efecto secundario del MPE: al crearlo se genera una managed virtual network que desactiva los starter pools → los Spark jobs arrancan en pools on-demand (3-5 min más lentos al inicio).
🌸 Analogía: el managed private endpoint es un túnel privado entre dos edificios de la misma ciudad (Fabric y Azure) sin salir a la calle. El on-premises gateway es el puente que cruza de tu pueblo (on-prem) a la ciudad (cloud). 🌉
21Orquestación: schedule vs evento vs encadenado
Necesito...
Solución
Horario fijo ("every weekday at 8AM")
Schedule en un pipeline
Reacción a un evento ("when a file is saved / a row arrives")
Encadenar A → luego B ("refresh after notebook succeeds")
Mismo pipeline con dependencia on-success
⚠️ Trampa clásica — Apache Spark Job Definition (SJD): NO orquesta, NO programa y NO reacciona a eventos. Solo empaqueta código Spark. Casi siempre es un señuelo en las preguntas de orquestación.
💡 Workflow event-driven: "when a file arrives → process it" = reflex item (el trigger que escucha el evento) + pipeline/notebook (la acción). Un fichero en la carpeta Files del lakehouse → OneLake event. "as soon as possible" → evento, NUNCA schedule.
🌸 Analogía: schedule = despertador (a las 8 en punto, pase lo que pase). Evento/reflex = sensor de movimiento (cuando pasa algo, salta). Encadenado = fichas de dominó (cuando cae la primera, cae la siguiente). El SJD es una fiambrera con código — guarda comida, no toca el despertador ni el sensor. ⏰
22runMultiple y DAGs
DAG = Directed Acyclic Graph = mapa de tareas con dependencias (qué va antes de qué), sin bucles. NO es un fichero: es una variable de Python dentro de una celda del notebook.
DAG = {
"activities": [ # lista de tareas
{"name": "NB1", "path": "NB1", "timeoutPerCellInSeconds": 300},
{"name": "NB2", "path": "NB2", "dependencies": ["NB1"]} # NB2 espera a NB1
],
"timeoutInSeconds": 43200
}
mssparkutils.notebook.runMultiple(DAG) # notebookutils = nuevo nombre
💡 runMultiple (solo notebooks, comparten sesión de Spark, ahorra CU) vs pipeline (mezcla tipos de actividad, conectores, triggers).
🌸 Analogía: un DAG son las instrucciones de montar un mueble de IKEA 🪑 — algunos pasos van en paralelo, otros esperan (no atornillas la puerta antes de montar la caja) y nunca vuelves atrás (sin bucles). runMultiple es el manual que dice el orden; activities son los pasos y dependencies las flechas de "esto antes que esto".
23Environments (librerías por defecto)
3 pasos en orden para tener librerías por defecto en el workspace:
Create an environment (el contenedor vacío).
Install the libraries (llenarlo).
Set the default environment (marcarlo como default).
⚠️ "Create a pool" y "Change runtime" son opcionales: distractores.
🌸 Analogía de la fiambrera 🍱: primero necesitas la fiambrera (create), luego metes la comida (install librerías) y luego dices "esta es la que se lleva todo el mundo por defecto" (set default). No puedes llenar una fiambrera que no existe.
📥
Dominio 2 · Ingerir y transformar (30-35%)
24Patrón de ingesta metadata-driven ⭐
Para la ingesta dinámica de N tablas listadas en una tabla de control, en una sola ejecución:
1. Lookup → lee la lista de la tabla de control → array
2. ForEach → recorre cada tabla del array
└─ 3. Copy data (inner) → copia esa tabla (parametrizada con @item())
🎯 Los 3 pasos en orden: Lookup (leer la lista) → ForEach (recorrer) → Copy data dentro del bucle.
⚠️ Trampas:
Lookup ≠ Get Metadata: el Lookup lee filas de una tabla/query; Get Metadata da info de ficheros y carpetas. Para leer la tabla de control → Lookup.
ForEach ≠ Until: ForEach recorre una lista conocida; Until repite hasta que se cumple una condición (while). Para "por cada tabla" → ForEach.
💡 Ventaja real: añadir una tabla = añadir una fila a la tabla de control, sin tocar el pipeline.
🌸 Analogía: es como una lista de la compra 🛒. Lookup = leer la lista. ForEach = recorrerla producto a producto. Copy = meter cada producto en el carro. Si mañana quieres comprar algo más, solo añades una línea a la lista, no rediseñas el supermercado.
25Ingesta: qué item usar
🎯 Asociaciones fiables:
On-premises + gateway + copy data → pipeline (Copy activity). (Nunca notebook/Spark: no hablan con el gateway on-prem.)
Copiar batch A→B sin transformar → pipeline con Copy activity.
Near-real-time + streamed from REST API + only Fabric → eventstream.
Transformación con código → notebook (si la fuente es accesible por Spark).
⚠️ Trampa: "streaming dataflow" y "streaming dataset" son señuelos frecuentes (el segundo es de Power BI clásico). La ingesta NRT nativa de Fabric es el eventstream.
26Copy activity → Warehouse (staging)
🎯 El Warehouse ingesta con COPY INTO, que solo lee directamente de Azure Blob y ADLS Gen2. Si el origen NO es compatible (Snowflake, on-prem, etc.) → Enable staging (staged copy): pasa por un storage intermedio y luego hace el COPY.
Origen → Warehouse
Configuración
Blob/ADLS Gen2
directo
Snowflake / on-prem / otros
Enable staging (obligatorio)
⚠️ El Lakehouse NO tiene esta restricción (usa Spark/Delta, no COPY INTO).
🌸 Analogía: el COPY INTO del warehouse solo acepta paquetes de dos mensajerías concretas (Blob y ADLS Gen2). Si tu paquete viene de otra mensajería (Snowflake), primero hay que llevarlo a una oficina intermedia compatible (staging) y desde ahí entra. 📦
27CDC (Change Data Capture)
🎯 CDC = función de una base de datos que registra automáticamente todos los cambios (inserts/updates/deletes). Es el "diario de cambios" que herramientas como el eventstream o el pipeline leen para propagarlos.
⚠️ Sin CDC activado → la BD no emite sus cambios → el eventstream/pipeline no tiene qué leer → no se propagan eventos.
💡 Regla: "stream record changes from a SQL DB" + "no se propagan" → Enable CDC en la BD origen.
No confundir:
CDC = captura cambios de DATOS (inserts/updates/deletes). ✅
Extended Events = diagnóstico y rendimiento (queries lentas, deadlocks). NO cambios de datos. ❌ señuelo.
Read-only replica = distribuir la carga de lecturas. ❌
🌸 Analogía: el CDC es el diario personal de la base de datos 📔 donde apunta cada cosa que cambia ("hoy se añadió esta fila, se borró esta otra"). Sin ese diario abierto, nadie de fuera puede enterarse de qué cambió. Extended Events es otro cuaderno distinto: el de "cómo de rápido voy" (diagnóstico), no el de "qué cambió".
28Caché de shortcuts
Para que un shortcut sirva datos desde la caché deben cumplirse LAS TRES condiciones:
Fuente cacheable: S3 / GCS / S3-compatible / on-premises gateway. ❌ ADLS Gen2 (Azure) NO (no hay egress cross-cloud que ahorrar).
Tamaño del fichero ≤ 1 GB (los > 1 GB nunca se cachean).
Último acceso dentro de la ventana de retención (por defecto 24 h; configurable de 1 a 28 días; cada acceso resetea el contador).
🎯 Algoritmo (aprende esto, no la respuesta — los números cambian):
¿Fuente cacheable? (S3/GCS sí, ADLS Gen2 no).
¿≤ 1 GB?
¿Accedido dentro de la retención?
Si falla cualquiera → va al origen, no a la caché.
🌸 Analogía: la caché es como guardar comida en la nevera para no ir al súper cada vez. Solo tiene sentido si (1) el súper está lejos y cobra por ir = fuente cross-cloud (a Azure no, que es la despensa de al lado), (2) el táper cabe en la nevera = ≤1 GB, y (3) no lleva ahí tanto tiempo que ya caducó = dentro de la retención. 🧊
29Patrón de carga: overwrite vs merge
Patrón híbrido con DeltaTable.forName como comprobación de existencia:
La tabla NO existe → write.mode('overwrite') (full load inicial) + return.
La tabla SÍ existe → MERGE (upsert incremental).
🎯 Cuidado con "always" en las preguntas de Sí/No:
"always overwritten" → No (solo la 1ª vez, cuando no existe).
"merge always runs" → No (solo si la tabla ya existe).
"supports full AND incremental" → Sí (overwrite = full la 1ª vez, merge = incremental después).
💡 overwrite = "escribe en modo reemplazo": si la tabla no existe, la crea; si existe, la reemplaza. NO necesita nada previo. Todos los modos (overwrite/append/error/ignore) crean la tabla si no existe; difieren solo en qué hacen si YA existe.
🌸 Analogía de la pizarra 📋: overwrite es escribir con rotulador — si la pizarra está vacía, escribes; si tenía algo, lo borras y escribes. En ambos casos acaba con TU mensaje. No necesitas que hubiera algo antes.
30Delta MERGE: whenMatched / BySource ⭐
targetDF.merge(sourceDF, "source.Key = target.Key")
.whenMatchedUpdate(set={...}) # existe en AMBAS → actualizar
.whenNotMatchedInsert(values={...}) # nueva en SOURCE → insertar
.whenNotMatchedBySourceUpdate( # huérfana en TARGET → inactivar/borrar
condition="...", set={"Status": "inactive"})
.execute()
Cláusula
¿A qué filas afecta?
whenMatched
existe en AMBAS (source ∩ target)
whenNotMatched
filas del SOURCE sin match → insertar
whenNotMatchedBySource
filas del TARGET que el source ya no trae (huérfanas) → actualizar/borrar
🎯 La clave es "BySource":
Sin "BySource" → mira desde el source ("nueva del origen" → insertar).
Con "BySource" → mira desde el target ("huérfana, el origen ya no la trae" → soft delete / inactivar).
🌸 Analogía: imagina que comparas tu lista de contactos (target) con la lista nueva de la empresa (source). Los que están en ambas → actualizas su teléfono (matched). Los nuevos de la empresa → los añades (notMatched, insertar). Los tuyos que ya no están en la lista de la empresa → los marcas como "ya no trabaja aquí" (notMatchedBySource). 📇
31Real-Time Intelligence: las 4 piezas ⭐
🌸 Analogía: una fábrica de paquetería 📦 donde los "paquetes" son datos que llegan sin parar:
Pieza
Qué hace
Analogía
Real-Time hub
catálogo/panel central de todo lo que fluye en tiempo real
la recepción/directorio 📋
Eventstream
mueve y transforma (ligero, no-code) del origen al destino
💡 Flujo: los datos entran por el hub → viajan por el eventstream → descansan en el eventhouse → el activator los vigila para reaccionar.
32Eventstream vs Notebook (transformar)
Eventstream
Notebook
Datos
streaming (en movimiento)
batch (en reposo)
Cómo
no-code (lienzo)
código (PySpark)
Potencia
ligera (filtrar, agregar)
compleja (dedup, ML)
🎯 Los datos en streaming fluyen sin parar → transformaciones ligeras para no atascar el flujo → eventstream (no-code). Streaming + complejo + código → Spark Structured Streaming (notebook, la excepción). Batch + código → notebook normal.
🌸 Analogía: el eventstream transforma la fruta mientras va por la cinta 🎞️ (lavarla, quitarle hojas — cosas rápidas al vuelo, sin parar la cinta). El notebook coge una caja de fruta del almacén 📦 y hace mermelada con calma (transformación compleja sobre datos quietos). Por eso el streaming solo admite transformaciones ligeras: no puedes hacer mermelada en plena cinta a toda velocidad.
33Windowing functions
Ventana
Cómo es
¿Solapa?
Uso
Tumbling
fija, pegadas, sin solapar
❌ No
conteos/medias por intervalo (per-minute)
Hopping
fija, avanza a saltos
✅ Sí
medias móviles (smoothed)
Sliding
recalcula por cada evento
✅ Sí
detección de anomalías
Session
dinámica, por huecos de inactividad
—
sesiones de usuario
🎯 Palabras clave que cantan cada una:
"non-overlapping / contiguous / each event in exactly one window / fixed intervals" → TUMBLING ⭐
"overlapping / moving average / smoothed / hop" → HOPPING
"inactivity gap / session / user activity / dynamic duration" → SESSION
🌸 Analogía de tumbling 🚌: es como los autobuses que salen cada hora en punto — cada pasajero (evento) coge exactamente uno, no se solapan y van pegados uno tras otro. Hopping serían autobuses que salen cada 30 min pero tardan 1 hora → te puedes montar en varios a la vez (solapan). Session es un autobús que espera hasta que deja de venir gente y entonces arranca (por huecos).
💡 Para agregaciones avanzadas por ventana temporal (como la desviación estándar) → Group by (permite elegir la ventana + la función estadística).
35OneLake availability en Eventhouse
Al activar la OneLake availability en un eventhouse/KQL, por defecto:
Solo fluye a OneLake lo que se ingiere a partir de ese momento (datos nuevos).
Los datos existentes NO se rellenan hacia atrás (no hay backfill).
🎯 Regla de oro: "you enable OneLake availability" (a secas) → only new data. Si mencionan explícitamente "apply to existing tables" → entonces new + existing.
💡 Bonus: con la OneLake availability activa en una tabla, NO puedes borrar/truncar/purgar datos, ni alterar el esquema, ni renombrar la tabla (restricciones del "one logical copy").
🌸 Analogía: activar la OneLake availability es como poner una cámara que empieza a grabar ahora 🎥 — graba de aquí en adelante, pero NO tiene grabado lo de antes (salvo que le pidas expresamente rellenar el histórico).
36KQL: operadores esenciales y prev()
Operador
Qué hace
where / filter
filtrar filas
sort by / order by
ordenar (¡DESCENDENTE por defecto! necesita asc)
extend
AÑADE una columna calculada
project
SELECCIONA columnas
prev() / next()
valor de la fila anterior/siguiente (¡requiere sort antes!)
summarize
agrupa y agrega
🎯 Reglas de oro:
sort/order by es DESCENDENTE por defecto → si piden "ascending" y falta asc → No cumple.
extend CREA columna, project ELIGE columnas.
prev()/next() necesitan sort/order by antes (serialización).
sort/order byantes de project es válido (el orden entre operadores es flexible).
KQL database + código T-SQL → No (lenguaje equivocado). KQL ordena DESCENDENTE por defecto; T-SQL ordena ASCENDENTE por defecto (son opuestos).
🌸 Mnemotécnica:extend eXtiende (añade) · project = eliges qué "proyectas" en pantalla. Y prev() es como preguntar "¿qué había en la fila de arriba?" — solo tiene sentido si antes has ordenado las filas (si están desordenadas, "la de arriba" no significa nada).
🎯 Deducir el tipo mirando la muestra de datos: fecha → datetime · texto → string · JSON/objeto/array → dynamic ⭐ · entero → int/long · decimal → real · true/false → bool.
⚠️ Trampas:JSON → dynamic (no long). Si una columna guarda JSON → dynamic. Y .create table es para tablas, .create function para funciones: no las confundas.
🌸 Analogía:dynamic es el cajón desastre de KQL 🗄️ — donde metes lo que no tiene forma fija (JSON, listas, objetos anidados). Las columnas "normales" (fecha, texto, número) van en cajones etiquetados; el JSON, al cajón flexible.
38PySpark: when / split / dropDuplicates
🎯 Detalles que caen en preguntas de Sí/No:
when((A) | (B), valor) → el | es OR: cubre A O B. Dos condiciones con | → reemplaza ambos casos (ej. null Y empty: isNull() | (col=="")).
split(col, "@").getItem(N) → índices base 0: getItem(0) = antes del separador (primer trozo); getItem(1) = después del separador (segundo trozo). ⚠️ Si el statement dice "before" pero el código usa item(1) (after) → falso.
dropDuplicates(["columna"]) → dedup por esa columna exacta. Si dice "por año" pero el código pone ["OrderDate"] (fecha completa) → no coincide → falso.
🌸 Truco: el | (OR) es una red que pesca varios tipos de pez a la vez (null Y vacío). Y en split(...).getItem(N), cuenta desde 0: item 0 = lo de antes de la @, item 1 = lo de después. 🎣
39Parámetros de pipeline: @ vs @{}
Sintaxis
Devuelve
@expresión (sin llaves)
valor con tipo nativo (int, bool...)
@{expresión} (con llaves)
siempre string (interpolación)
@@
escape → string literal que empieza por @
🎯 "return as int / preserve type" → @ sin llaves (@pipeline().parameters.param1). "Construir un texto con valores dentro" → @{ } con llaves.
🌸 Analogía: las llaves {} son como comillas — todo lo que metes dentro se convierte en texto (string). Sin llaves, el valor sale "tal cual" con su tipo original (un número sigue siendo número). Si necesitas que siga siendo un int → sin llaves.
📊
Dominio 3 · Monitorizar y optimizar (30-35%)
40Mantenimiento Delta: OPTIMIZE vs VACUUM
Necesito...
Comando
Consolidar / compactar ficheros pequeños en grandes
OPTIMIZE
Co-localizar datos por columnas que se filtran a menudo
OPTIMIZE ... ZORDER BY (col)
Borrar ficheros obsoletos / no referenciados / limpiar el historial
VACUUM (por defecto retiene 7 días / 168 h)
Optimización de escritura de Fabric (lecturas rápidas)
🌸 Analogía: OPTIMIZE es juntar mil papelitos sueltos en pocas carpetas ordenadas 📁 (menos ficheros, más grandes → lecturas rápidas). VACUUM es tirar a la basura los papeles viejos que ya no usas 🗑️. Uno junta, el otro tira.
41V-Order: el trade-off lectura/escritura ⭐
🎯 V-Order optimiza LECTURAS pero añade overhead a las ESCRITURAS. Es un trade-off.
⚠️ Pista: "write-intensive + minimize LOAD time + tables read once and dropped" → Disable V-Order (las tablas casi no se leen, no compensa el overhead de escritura). V-Order ya está ON por defecto.
🌸 Analogía: V-Order es como doblar y ordenar la ropa perfectamente antes de guardarla 👕 — tardas más al guardar (escribir), pero luego la encuentras rapidísimo (leer). Si vas a sacar esa ropa una sola vez y tirarla, no merece la pena doblarla tan bien → mejor guardar rápido (disable V-Order).
42Statistics para optimizar queries
🎯 Las statistics (histogramas, cardinalidad) las usa el query optimizer para elegir el mejor plan. Unas stats desactualizadas (tras crecer la tabla) → planes malos → queries lentas. Actualizarlas → queries rápidas.
💡 "optimize query experience / queries lentas porque los datos crecieron" → Create/update statistics.
⚠️ No confundir con la optimización de escritura (eso es V-Order/OPTIMIZE). Las statistics optimizan lecturas y queries.
🌸 Analogía: las statistics son el mapa actualizado del almacén 🗺️ que usa el mozo (el optimizer) para elegir la ruta más rápida. Si el almacén creció y el mapa está viejo, el mozo da vueltas de más (queries lentas). Actualizas el mapa → rutas óptimas.
43Direct Lake: el tipo de dato de las keys
🎯 En Direct Lake, todo se carga comprimido en memoria. Los strings largos (MD5, SHA256, GUIDs) son enemigos cuando se repiten en millones de filas → hinchan el modelo → exceden los guardrails → fallback a DirectQuery o errores en los visuals. Los enteros (INT/BIGINT) son amigos (comprimen genial).
💡 Patrón: "surrogate keys con hash" + "Direct Lake" + "performance/errors" + "millones de filas" → sospecha del tipo de dato de las keys → cámbialas a entero.
⚠️ NO "increase capacity" (viola el coste), NO SHA256 (un string aún más largo).
🌸 Analogía: guardar en memoria un string MD5 largo repetido millones de veces es como meter cajas enormes vacías que ocupan toda la estantería. Un entero es una caja pequeñita que comprime genial. Cambias las cajas grandes por pequeñas → cabe todo y va rápido. 📦
44Optimización KQL: filtrar temprano ⭐
🎯 LA optimización nº1: FILTRAR LO ANTES POSIBLE. Mover el filter/whereantes de las operaciones costosas (join, summarize) reduce las filas que se procesan → mucho más rápido.
Solución propuesta
¿Optimiza?
Mover el filter antes del join
✅ Sí (filtra pronto)
hint.strategy=broadcast (tabla pequeña)
✅ Sí
Cambiar inner → outer
❌ No (más filas, cambia los resultados)
Cambiar project → extend
❌ No (añade columnas)
Añadir make_list()
❌ No (agregación extra)
💡 Truco: ¿el cambio REDUCE datos antes de la parte cara? → optimiza. ¿Añade trabajo o cambia resultados? → No.
🌸 Analogía: si vas a hacer un cóctel con solo las naranjas maduras 🍊, ¿qué es más rápido: exprimir TODAS las naranjas y luego tirar las verdes, o quitar las verdes primero y exprimir solo las buenas? Filtrar antes = menos trabajo. Aplica igual en KQL: filtra antes del join.
45Herramientas de monitorización (cuál es cuál)
Herramienta
Para qué sirve
Fabric Monitor / Monitor hub
Ver ejecuciones (runs) de notebooks, pipelines, dataflows y Spark jobs: estado, duración, snapshots, versión de runtime/Delta.
Capacity Metrics app
Consumo de capacidad (CU): bursting, smoothing, throttling.
Admin monitoring workspace
Informes de uso y auditoría a nivel tenant (adopción, actividad de la organización).
Real-Time hub
Datos en streaming y eventos en tiempo real (no monitoriza jobs).
OneLake catalog / data hub
Descubrir datos (encontrar items).
🎯 Trucos: "¿Qué pasó en una ejecución concreta?" (estado, duración, versión) → Monitor hub. "¿Cuánta capacidad se gastó?" → Capacity Metrics app. "Auditoría a nivel organización" → Admin monitoring workspace.
46Monitorización de queries (DMVs): histórico vs tiempo real ⭐
Necesito...
Herramienta
Queries históricas (últimos X min/días) + usuario + texto
queryinsights schema ⭐
Query corriendo AHORA + duración
sys.dm_exec_requests
Nombres de usuarios en sesiones activas
sys.dm_exec_sessions (login_name)
Conexión física (IP, protocolo)
sys.dm_exec_connections
Consumo de capacidad (CU)
Capacity Metrics app
🎯 Reglas:
sys.dm_exec_* = TIEMPO REAL (lo que pasa ahora; desaparece al acabar).
"last 60 minutes / durante las últimas X" (pasado) → queryinsights.
"currently running / en vivo" → dm_exec_requests.
"names of users" → dm_exec_sessions (tiene login_name).
🌸 Analogía: las DMVs dm_exec_* son la cámara en directo 📹 (ves lo que pasa AHORA; cuando acaba, se va). queryinsights es la grabación guardada 📼 (puedes ver lo de hace un rato). Para "los últimos 60 minutos" necesitas la grabación, no el directo.
47Refrescar semantic model: execute vs monitor
🎯 La palabra clave manda:
"dynamically EXECUTE" (+ monitor) un refresh → semantic link (sempy) en un notebook. Es el único que lanza el refresh Y lo monitoriza programáticamente.
"MONITOR" (solo ver) el histórico → Monitoring hub, DMVs o el refresh history del modelo.
⚠️ Trampa: el Monitoring hub y las DMVs solo MONITORIZAN (leen), NO EJECUTAN refreshes. Si el enunciado pide "execute" → necesitas código (semantic link).
🌸 Analogía: el Monitoring hub es la ventana desde la que miras si la lavadora ha terminado 👀 (solo observas). Semantic link (sempy) es el mando a distancia que además enciende la lavadora 🎛️. Si te piden "encender Y vigilar" → necesitas el mando, no solo mirar por la ventana.
48Debug de pipeline: input vs output JSON ⭐
Cuando una actividad falla, en el Monitoring hub → run fallido → tienes dos JSONs:
JSON
Contiene
Para...
Input
la configuración/query con la que se ejecutó (lo que recibió)
"¿QUÉ se le pidió hacer?" (la SQL query) ⭐
Output
resultado, filas copiadas, error, stats (lo que produjo)
"¿QUÉ obtuvo / qué error?"
🎯 "which SQL query was executed" → INPUT JSON (la query es un parámetro de entrada, especialmente con un source dinámico).
⚠️ El output tiene el error y el resultado, pero NO la query. La query es lo que entra. Debug de pipeline → Monitoring hub, NO Real-time hub.
🌸 Analogía: el input es la nota que le das a alguien ("hazme esta compra con esta lista") 📝; el output es lo que trae de vuelta (el ticket y las bolsas) 🛍️. Si quieres saber qué le pediste (la query), miras la nota (input), no las bolsas.
49Exhibit de pipeline: Inactive y flechas
🎯 El estado "Inactive" de una actividad significa que está DESACTIVADA (comentada). Una actividad inactiva nunca se ejecuta: se salta (skipped) en cada run, sin importar las dependencias.
Flechas de dependencia (cómo leer el exhibit):
Sin flecha entre cajas → paralelo (simultáneas).
Con flecha → secuencia. Colores: 🟢 verde = on success, 🔴 rojo = on failure, 🔵 azul = on completion, ⚫ gris = on skip.
🌸 Analogía: una actividad Inactive es como una tarea tachada en tu lista ✍️ — sigue escrita, pero no la haces. Y las flechas entre actividades son las reglas del dominó: sin flecha, las fichas caen a la vez (paralelo); con flecha, una espera a la otra (secuencia).
50Monitorización Spark: History Server vs run series
Necesito ver...
Herramienta
Jobs/stages de UN run en timeline
Spark History Server (Event Timeline) ⭐
Comparar VARIOS runs (tendencia de duración)
run series
Listado de ejecuciones y estado
Monitoring hub
Progreso en vivo por celda
contextual monitoring (dentro del notebook)
🎯 Diferencia clave: el run series compara VARIAS ejecuciones (cada barra = un run), mostrando la tendencia entre runs. El Spark History Server muestra los jobs/stages DENTRO de UN run, en timeline.
🌸 Analogía: el run series es comparar tus tiempos de las últimas 10 carreras 🏃♀️ (¿voy mejorando?). El Spark History Server es el desglose minuto a minuto de UNA carrera concreta (¿cuánto tardé en cada tramo?). Para "los jobs de un run en timeline" → la carrera concreta → History Server.
🎓
Extra: meta-estrategia
51Meta-estrategia: cómo pensar como el examinador
Patrones de comportamiento de las preguntas que conviene interiorizar:
🔑 "Least privilege" = descarta el rol o permiso más poderoso. Elige el mínimo que cumpla la tarea.
🔑 Frases "de relleno" ("you already assigned...", "Inactive") = NO son relleno. Resuelven medio requisito y cambian la respuesta. Léelas dos veces.
🔑 Case studies: la respuesta sale de cazar la frase exacta del requisito (busca el verbo clave: transform vs copy vs cleanse), no de tu preferencia de herramienta.
🔑 "Qué artefacto uso": tacha cada requisito uno a uno sobre cada opción. Gana el que no falla ninguno, no el de la palabra que más suena.
🔑 Una sola palabra (ej. "KQL", "LOAD time", "last 60 minutes") puede desviarte o ser la clave. Léela con atención.
🔑 "always" en preguntas de Sí/No → casi siempre No (si el código tiene ramas if/try).
🔑 Series de preguntas que repiten el escenario → cambian UN detalle cada vez; lee cada una fresca.
🔑 Optimización de queries → filtrar temprano es casi siempre la respuesta.
🔑 Aprende algoritmos, no respuestas: las preguntas de caché, permisos y DMVs tienen variantes con los números cambiados. Domina el procedimiento.
🔑 El examen abstrae la implementación: "migrate table" es un paso en el examen; en la vida real es un proyecto entero.
🌸 La lección más útil de todas: si una pregunta parece imposible, casi siempre es que aún no la has leído despacio. Respira, léela dos veces, mira los datos con calma y descompón en piezas. La respuesta suele estar ahí.
52Cuando la doc gana al dump
Los volcados de preguntas de examen ("dumps") son útiles para practicar el formato y los temas, pero tienen errores: respuestas mal marcadas, opciones que faltan o contenido desactualizado (Fabric cambia rápido). Cuando una respuesta marcada choca con la documentación oficial de Microsoft Learn, gana la documentación.
Casos donde conviene desconfiar del dump y verificar en la doc:
Tema
Lo que suele marcar el dump
Lo que dice la doc
Aislamiento de sesiones Spark
custom pool
disable high concurrency
OneLake availability (eventhouse)
new + existing
only new data por defecto (sin backfill)
Scheduled refresh en deployment pipelines
se despliega
NO se despliega
Endorsement de dashboards
Certified/Master data
Cannot be endorsed
DMV para usuarios activos
dm_exec_requests
dm_exec_sessions (tiene login_name)
Direct Lake + MD5 keys
varias
cambiar el tipo de dato (string→int)
StdDev en Eventstream
Aggregate
Group by
Optimizar queries del warehouse
V-Order
statistics (V-Order ya está ON)
🎯 Meta-regla: aprende el procedimiento y el razonamiento, no la respuesta memorizada. Ante una opción "que suena bien pero no cuadra con la doc", confía en tu razonamiento + la documentación oficial.
💜 Guía maestra viva. Se irá ampliando y puliendo con la experiencia. Hecha con cariño para ayudar a quien venga detrás a preparar el DP-700. 🌸✨