El motor de cómputo del data engineering: arquitectura, pools, nodos, runtimes, environments, optimizaciones, notebooks vs Spark Job Definitions, DataFrames, particionado, Spark SQL y visualización. 🌸
IntermedioAvanzado
🎯
1. Objetivos y encaje en el DP-700
¿Qué te enseña este módulo?
Este es el módulo donde aprendemos a usar el motor de cómputo del data engineering en Fabric. Los objetivos oficiales:
Configurar Spark en un workspace de Fabric.
Identificar escenarios adecuados para notebooks Spark y Spark jobs.
Usar Spark dataframes para analizar y transformar datos.
Usar Spark SQL para consultar datos en tablas y vistas.
Visualizar datos en un notebook Spark.
Peso en el examen DP-700
Este módulo es fundamental para el Dominio 2 (Ingest and transform) y aparece transversalmente en el resto:
Dominio
Cómo aparece Spark
Implement and manage (30-35%)
Configuración de pools, runtimes y environments a nivel workspace
Ingest and transform (30-35%)
PySpark y Spark SQL para transformar en notebooks, patrones de escritura Delta
Monitor and optimize (30-35%)
Optimizaciones de Spark (autoscale, dynamic allocation, native execution engine, autotune)
🎯 Qué es NUEVO respecto a la DP-600
En DP-600 se toca Spark de pasada (crear un notebook, hacer un spark.read.load()). En DP-700 hay que dominar la configuración, los conceptos de rendimiento y los matices de PySpark. Cosas que salen que antes no:
🆕 Native Execution Engine (vectorized processing)
🆕 High Concurrency Mode (compartir sesiones)
🆕 Environments (custom Spark configs por workload)
🆕 Runtime 1.3 vs 2.0 (versiones de Spark/Delta)
🆕 Elección Python kernel vs Spark kernel
🆕 NotebookUtils (antes MSSparkUtils)
🆕 Autotune para optimización automática
🔥
2. ¿Qué es Apache Spark?
Definición
Apache Spark es un framework de procesamiento distribuido de datos open-source. Su gran idea: cuando tienes muchísimos datos que no caben ni se procesan bien en una sola máquina, Spark distribuye el trabajo entre varias máquinas (nodos) y coordina la ejecución.
En Fabric, ese conjunto de máquinas se llama un Spark pool.
La filosofía "divide y vencerás"
Piensa en Spark como una fábrica de galletas kawaii 🍪:
Si tienes que hacer 10 galletas → una persona sola, en su cocina, las hace.
Si tienes que hacer 1 millón de galletas → necesitas repartir el trabajo entre muchos operarios en muchas cocinas trabajando en paralelo.
Spark es "el gerente" que decide qué operario hace cada parte, recoge los resultados y te devuelve las galletas terminadas. 🌸
Lenguajes soportados
Spark ejecuta código escrito en varios lenguajes:
PySpark (Python) → el más popular
Spark SQL → sintaxis SQL clásica
Scala → el "nativo" de Spark
SparkR → R
Java → el más verboso, poco común
En la práctica, PySpark y Spark SQL cubren el 95% de los casos.
🎯 Notación clave
Cuando escribes código Spark, casi siempre acabas invocando el objeto spark (una SparkSession). Es el punto de entrada a todo:
spark # <-- Objeto SparkSession, ya está creado automáticamente en cada notebook
Desde spark puedes leer, escribir, ejecutar SQL, gestionar el catálogo, etc.
🏗️
3. Arquitectura: driver, workers y executors
Este apartado es más "conceptual" pero cae en preguntas de troubleshooting.
Los tres tipos de "procesos" en Spark
A) Driver (uno solo)
Vive en el head node.
Es el "cerebro": recibe tu código, lo compila, planifica cómo distribuirlo, y coordina.
Contiene la SparkSession (el objeto spark).
Si el driver se cae → la sesión entera se cae.
B) Workers (varios)
Son las máquinas que hacen el trabajo real.
Cada worker es un nodo del pool.
C) Executors (uno o varios por worker)
Son los procesos que ejecutan tareas dentro de cada worker.
Pueden ejecutar múltiples tareas en paralelo (dependen de cores).
🎯 Detalle crítico en Fabric
En Fabric, la ratio nodos a executors es siempre 1:1. Cuando configuras un pool con N nodos, uno se reserva para el driver y los demás son executors.
Excepción: en configuración single-node, el driver y el executor comparten recursos (divididos por 2 aprox.).
Un Spark pool es el conjunto de nodos de cómputo que ejecuta el trabajo Spark. Fabric ofrece dos tipos:
4.1 · Starter pool
Un starter pool se crea automáticamente en cada workspace de Fabric. Es un pool pre-hidratado ("live pool"), lo que significa que los nodos ya están calentitos esperando.
Ventajas:
⚡ Arranque muy rápido (~segundos) porque los nodos están live.
🚀 Ideal para desarrollo, exploración, casos ad-hoc.
💰 Compartido entre workloads.
Limitaciones:
Configuración limitada (medium size por defecto).
No permite ciertas configuraciones avanzadas como managed private endpoint o private link.
4.2 · Custom Spark pool
Un custom Spark pool lo defines tú con configuración específica. Necesarios cuando:
Tienes cargas de trabajo que necesitan más recursos o configuraciones específicas.
Necesitas Private Link / Managed Private Endpoint.
Quieres fine-tune del cost/performance para un workload concreto.
Puedes configurar:
Node family: Memory Optimized (única disponible en Fabric).
Node size: desde Small hasta XX-Large.
Autoscale: rango min-max de nodos.
Dynamic allocation of executors: rango min-max de executors.
4.3 · 🎯 Custom live pools (feature interesante)
Los custom live pools son custom pools con arranque en ~5 segundos (como el starter pool). Requieren un environment con "Full mode for library publishing".
Sin esta configuración, un custom pool tarda ~3 minutos en arrancar. Un starter pool ya está caliente.
4.4 · Prerequisitos para crear custom pools
Para crear un custom pool necesitas:
Rol Admin en el workspace.
Un capacity admin ha habilitado "Customized workspace pools" en Spark Compute settings de la capacidad.
Si no tienes estos permisos → solo puedes usar el starter pool.
Se puede desactivar si prefieres un escalado más suave.
5.4 · Dynamic allocation of executors
Dynamic allocation ajusta el número de executors (no de nodos) según la carga del job:
Cuando la app Spark tiene muchas tareas pendientes → pide más executors.
Cuando la app está idle o terminó → libera executors.
Configuras un min y max de executors.
Es muy útil porque las cargas de un job varían por fase (leer datos → shuffle → agregar → escribir). Los executors necesarios son distintos en cada fase.
5.5 · 🎯 Diferencia autoscale vs dynamic allocation
⚠️ Ojo cosita: %%configuretiene que ser la primera celda del notebook para que aplique.
8.2 · 🎯 High Concurrency Mode
Qué es: modo que permite compartir una sesión Spark entre múltiples notebooks/usuarios simultáneamente.
Ventajas:
Reduce startup overhead (no arranca sesión nueva cada vez).
Ahorro de recursos cuando hay muchos users trabajando en paralelo.
Mantiene isolation: variables de un notebook no afectan a otro.
Requisitos para compartir sesión:
Mismo lakehouse
Mismo environment
Misma configuración Spark
Cómo activar: Workspace settings → Data Engineering/Science → activar toggle.
También aplicable a Spark jobs (no solo notebooks).
⚠️ Sesiones activas acumulan CU utilization. Timeout por defecto: 20 minutos. Parar sesiones cuando no las uses.
8.3 · 🎯 V-Order
Ya lo vimos en el Módulo 2. Recordamos:
Optimización de escritura Parquet exclusiva de Fabric.
Activado por defecto (spark.sql.parquet.vorder.enabled = true).
Reordena datos para acelerar lecturas desde motores columnar (Power BI, Warehouse).
Pequeño overhead al escribir, gran beneficio al leer.
8.4 · Autotune
Autotune es una feature que aprende automáticamente las mejores configuraciones Spark para tus queries recurrentes:
Modela las queries que ejecutas.
Optimiza settings con cada iteración.
Necesita ~20-25 iteraciones para converger.
⚠️ Solo compatible con Runtime 1.2 (retirado). No funciona en runtimes actuales. Si te aparece en preguntas de examen, ten en cuenta que puede estar desactualizado.
8.5 · Automatic MLFlow logging
MLFlow es un tracking system open-source para machine learning. En Fabric:
Se usa por defecto para loguear implícitamente actividad de experimentos ML.
No necesitas añadir código explícito.
Se puede desactivar en workspace settings.
8.6 · Adaptive Query Execution (AQE)
Habilitado por defecto en todos los runtimes de Fabric. Ajusta dinámicamente:
Número de shuffle partitions.
Estrategias de join.
Manejo de skew (particiones desbalanceadas) → spark.sql.adaptive.skewJoin.enabled.
📝
9. Cómo ejecutar código Spark: notebooks vs Spark Job Definitions
Hay dos formas principales de ejecutar código Spark en Fabric. Cae mucho en preguntas escenario.
9.1 · Notebooks
Un notebook es un item interactivo web-based que:
Combina celdas de código y celdas de markdown/texto.
Ideal para exploración, desarrollo, análisis interactivo, ML.
9.2 · Spark Job Definition
Un Spark Job Definition (SJD) es un item que:
Ejecuta un script Python/JAR de forma no interactiva.
Se puede ejecutar on-demand o por schedule.
Se referencia desde pipelines para automatización.
Puede especificar ficheros de referencia (código, config).
Ideal para producción y ETL automatizado.
9.3 · 🎯 Regla de decisión para el examen
Necesitas…
Usa
Explorar datos interactivamente
Notebook
Prototipar transformaciones
Notebook
Machine learning con visualizaciones inline
Notebook
Colaborar con markdown y análisis
Notebook
ETL programado en producción
Spark Job Definition
Ejecutar un script Python puro sin UI
Spark Job Definition
Orquestar desde un pipeline
Puede ser cualquiera, pero SJD es más "producción-ready"
⚠️ Ojo: notebooks TAMBIÉN se pueden orquestar desde pipelines (actividad "Notebook"). Es muy común en Fabric. Pero para código puramente batch sin UI → SJD es más limpio.
9.4 · Estructura de un notebook
Un notebook tiene:
Celdas de código: Python, Spark SQL, Scala, R, HTML, etc.
Celdas markdown: documentación, título, imágenes.
Un lenguaje primario: el default para todas las celdas nuevas.
Un lakehouse asignado por defecto: para que Files/ y Tables/ funcionen sin path completo.
✨
10. Magic commands en notebooks
Los magic commands son comandos especiales que empiezan con % (line magic) o %% (cell magic). Sirven para cambiar comportamiento de una celda o del notebook completo.
10.1 · 🎯 Magics de lenguaje (cambiar idioma de una celda)
Magic
Lenguaje
Descripción
%%pyspark
Python
Ejecuta Python contra el Spark Context
%%spark
Scala
Ejecuta Scala contra el Spark Context
%%sql
Spark SQL
Ejecuta SQL contra el Spark Context
%%sparkr
R
Ejecuta R contra el Spark Context
%%html
HTML
Renderiza HTML
%%csharp
C#
Ejecuta .NET for Spark C#
Ejemplo:
# Celda en un notebook con lenguaje primario = PySpark
%%sql
SELECT * FROM my_delta_table LIMIT 10
En esa celda concreta, Fabric ejecuta como SQL aunque el notebook sea PySpark. 🌸
10.2 · 🎯 Magics útiles para configuración
Magic
Uso
%%configure
Configurar Spark (debe ser la 1ª celda)
%pip install X
Instalar librería PyPI en la sesión
%conda install X
Instalar con conda
Ejemplo de %%configure (activar Native Execution Engine):
Cuando ejecutas un notebook desde un pipeline (actividad Notebook), solo estos magics están soportados:
%%pyspark
%%spark
%%csharp
%%sql
%%configure
Si usas otros → pueden fallar en pipeline.
10.5 · Custom magic commands
Puedes definir tus propios magic commands en un notebook y llamarlos desde otro. Útil para funcionalidades reutilizables.
🛠️
11. NotebookUtils (antes MSSparkUtils)
11.1 · ¿Qué es NotebookUtils?
NotebookUtils (antes llamado MSSparkUtils) es una librería built-in para tareas comunes en notebooks:
Manejar el file system.
Obtener environment variables.
Encadenar notebooks.
Manejar secrets.
Utilities de credentials.
Está disponible en PySpark, Scala, SparkR notebooks y pipelines.
11.2 · ⚠️ Renaming importante
En 2024 se renombró oficialmente:
Antes: mssparkutils
Ahora: notebookutils
El código antiguo sigue funcionando (backward compatible), pero se recomienda migrar. El namespace mssparkutils se retirará en el futuro.
Requisito: Spark 3.4 (Runtime v1.2) o superior.
11.3 · Uso básico
import notebookutils
# Ver ayuda de todos los comandos disponibles
notebookutils.notebook.help()
11.4 · Ejemplos útiles
Trabajar con file system (fs):
# Listar ficheros
files = notebookutils.fs.ls("Files/my_folder")
# Leer un fichero de texto
content = notebookutils.fs.head("Files/config.json", 1024) # Primeros 1024 bytes
# Copiar entre ubicaciones
notebookutils.fs.cp("Files/source.csv", "Files/backup/source.csv")
# Borrar
notebookutils.fs.rm("Files/temp.txt")
# Crear directorio
notebookutils.fs.mkdirs("Files/new_folder")
Encadenar notebooks:
# Ejecutar otro notebook y esperar
result = notebookutils.notebook.run("path/to/other_notebook", timeout_seconds=60, args={"param1": "value1"})
# Ejecutar múltiples notebooks en paralelo (DAG)
notebookutils.notebook.runMultiple([
{"path": "notebook1"},
{"path": "notebook2", "dependencies": ["notebook1"]},
{"path": "notebook3", "dependencies": ["notebook1"]}
])
Salir de un notebook con valor:
# Sale del notebook devolviendo un valor al llamador
notebookutils.notebook.exit("Success: 1000 rows processed")
Obtener credentials (secrets):
# Obtener secret de un Azure Key Vault vinculado
secret = notebookutils.credentials.getSecret("kv-name", "secret-name")
11.5 · 🎯 runMultiple() para DAGs
notebookutils.notebook.runMultiple() es SUPER poderoso: ejecuta notebooks con dependencias tipo DAG. Excelente para orquestar pipelines medallion (bronze → silver → gold).
Este es el corazón de PySpark. Vamos a fondo con ejemplos comentados 💕
12.1 · ¿Qué es un DataFrame?
Un DataFrame es una tabla distribuida con filas y columnas. Es lo mismo que un DataFrame de Pandas pero optimizado para procesamiento distribuido.
Nativamente, Spark tiene RDDs (Resilient Distributed Datasets), pero DataFrames son el estándar moderno: más eficientes, con schema, y con API declarativa.
En Fabric usamos DataFrames el 99% del tiempo.
12.2 · Cargar datos en un DataFrame
A) Con schema inferido (opción rápida)
%%pyspark
# Leer un CSV con schema inferido automáticamente por Spark
df = spark.read.load(
'Files/data/products.csv', # Ruta al fichero (relativa al lakehouse por defecto)
format='csv', # Formato del fichero
header=True # La primera fila son los headers
)
# Mostrar las primeras 10 filas en formato tabla
display(df.limit(10))
Equivalente en Scala:
%%spark
val df = spark.read.format("csv").option("header", "true").load("Files/data/products.csv")
display(df.limit(10))
B) Con schema explícito (mejor rendimiento y validación)
%%pyspark
from pyspark.sql.types import StructType, StructField, IntegerType, StringType, FloatType
# Definir schema explícito
productSchema = StructType([
StructField("ProductID", IntegerType()), # Columna entera
StructField("ProductName", StringType()), # Columna texto
StructField("Category", StringType()),
StructField("ListPrice", FloatType()) # Columna decimal
])
# Cargar CSV con schema (sin header en este ejemplo)
df = spark.read.load(
'Files/data/product-data.csv',
format='csv',
schema=productSchema, # Se aplica el schema definido
header=False # El CSV no tiene fila de cabecera
)
display(df.limit(10))
💡 Tip oficial: "Specifying an explicit schema also improves performance!" Cuando Spark no tiene que inferir el schema, es mucho más rápido.
12.3 · Formatos que puedes leer
Spark en Fabric lee (spark.read.format('X').load()) prácticamente todo:
Análogo mental: es como componer un pipeline de Power Query paso a paso.
12.6 · Guardar un DataFrame
Guardar como Parquet (formato analítico eficiente):
# Sobrescribir cualquier fichero existente en esa ruta
bikes_df.write.mode("overwrite").parquet('Files/product_data/bikes.parquet')
Modos de escritura (.mode()):
Modo
Descripción
overwrite
Borra lo existente y escribe de nuevo
append
Añade a lo existente
ignore
No hace nada si ya existe
error / errorifexists (default)
Falla si ya existe
Guardar como Delta (preferido en lakehouse):
# Como tabla Delta gestionada (aparece en el catálogo del lakehouse)
df.write.format("delta").saveAsTable("mi_tabla_delta")
# Como fichero Delta en una ruta específica
df.write.format("delta").mode("overwrite").save("Files/my_delta_folder")
📁
13. Particionado de datos
El particionado es una técnica de optimización que permite a Spark procesar en paralelo mejor y filtrar datos más rápido.
13.1 · Qué es particionar
Particionar = dividir el output en subcarpetas basadas en el valor de una o varias columnas.
Por ejemplo, si tienes datos de ventas y particionas por year y month, obtienes:
# Particionar por una columna
bikes_df.write.partitionBy("Category").mode("overwrite").parquet("Files/bike_data")
# Particionar por varias columnas (jerarquía)
sales_df.write.partitionBy("year", "month").mode("overwrite").parquet("Files/sales_data")
Las carpetas generadas siguen el formato columna=valor/, que es el estándar Hive-style.
13.3 · Beneficios del particionado
⚡ Predicate pushdown: si filtras por la columna particionada, Spark lee solo las particiones relevantes, no todo el dataset.
🚀 Paralelismo: cada partición se puede procesar en un executor distinto.
💾 Compresión mejor: datos similares agrupados comprimen mejor.
Ejemplo de filtro que se beneficia:
# Spark solo lee la partición year=2026
df_2026 = spark.read.parquet("Files/sales_data/year=2026")
O con filter automático:
# Spark hace "partition pruning" y solo lee la partición relevante
df = spark.read.parquet("Files/sales_data").filter(col("year") == 2026)
13.4 · ⚠️ Cuándo NO particionar
Si tu columna tiene cardinalidad muy alta (miles/millones de valores únicos) → generas miles de particiones minúsculas. Es peor que no particionar.
Ejemplos malos: user_id, order_id, timestamp a nivel segundo.
# Todas las particiones 2024-2025
some_data = spark.read.parquet("Files/sales_data/year=202[4-5]")
⚠️ Trampa: cuando lees directamente una partición (opción B), la columna particionada desaparece del DataFrame (porque Spark ya sabe que todo son "Road Bikes"). Si haces road_bikes.columns, no verás Category.
🗂️
14. Spark SQL: catalog, temporary views y tablas
Spark tiene un catalog (metastore) que registra objetos relacionales para consultarlos con SQL.
14.1 · Catalog
El Spark catalog es el metastore que registra:
Databases (schemas)
Tables (managed o external)
Views (persistentes o temporary)
Functions
En Fabric, el catalog del lakehouse tiene tus tablas Delta bajo dbo (o schemas custom si tienes schema-enabled lakehouse).
14.2 · Temporary views
Una temporary view es una vista efímera que existe solo durante la sesión. Se autodestruye al cerrar la sesión.
Uso típico: hacer queriable un DataFrame con SQL sin persistirlo como tabla.
# Convierto un DataFrame en una vista temporal consultable
df.createOrReplaceTempView("products_view")
# Ahora puedo consultar con SQL
result = spark.sql("SELECT * FROM products_view WHERE Category = 'Bikes'")
display(result)
# O directamente con magic
%%sql
SELECT * FROM products_view WHERE Category = 'Bikes'
Al terminar la sesión → la vista desaparece. Los datos originales del DataFrame también desaparecen si no los guardaste.
14.3 · Tablas managed
Las tablas managed son las que Fabric gestiona completamente (metadata + datos). Los datos van a Tables/ del lakehouse por defecto.
Crear con saveAsTable:
# Convierte el DataFrame en una tabla Delta gestionada
df.write.format("delta").saveAsTable("products")
# Con schema específico
df.write.format("delta").saveAsTable("sales.orders") # requiere schemas habilitados
Delta es el formato preferido en Fabric para tablas:
Transacciones ACID
Time travel
Schema enforcement
V-Order
Aparece en SQL analytics endpoint
Otros formatos (Parquet, CSV) NO aparecen en SQL analytics endpoint.
14.6 · Consultar con Spark SQL
Con la API spark.sql():
# Devuelve un DataFrame
bikes_df = spark.sql("""
SELECT ProductID, ProductName, ListPrice
FROM products
WHERE Category IN ('Mountain Bikes', 'Road Bikes')
""")
display(bikes_df)
Con magic %%sql:
%%sql
SELECT Category, COUNT(ProductID) AS ProductCount
FROM products
GROUP BY Category
ORDER BY Category
Los resultados se muestran automáticamente como tabla en el notebook.
14.7 · 🎯 Casos de uso
spark.sql(): cuando quieres usar el resultado en Python (asignar a variable, seguir procesando).
%%sql: cuando quieres solo ver el resultado en pantalla, exploración rápida.
14.8 · Referencias four-part namespace
Si tienes schemas habilitados:
-- Referencia completa
SELECT * FROM my_workspace.my_lakehouse.sales.orders
-- Referencia dentro del mismo workspace
SELECT * FROM my_lakehouse.sales.orders
-- Referencia dentro del mismo lakehouse (schema explícito)
SELECT * FROM sales.orders
-- Referencia al schema por defecto (dbo)
SELECT * FROM orders
📈
15. Visualización en notebooks
15.1 · Charts built-in del notebook
Cuando ejecutas una celda que devuelve un DataFrame o SQL query, el resultado sale como tabla. Puedes cambiar a modo chart desde la UI del notebook:
Barra debajo de los resultados → botón Chart.
Configurar chart type, dimensiones, agregaciones desde la UI.
Es rápido para exploración pero limitado en personalización.
15.2 · Matplotlib
Matplotlib es la librería base de visualización en Python. Está pre-instalada en el runtime de Fabric.
Requisito importante: Matplotlib necesita datos en Pandas DataFrame, no en Spark DataFrame.
Para convertir:
# Convertir de Spark a Pandas (¡cuidado con datasets grandes!)
pandas_df = spark_df.toPandas()
⚠️ Ojo cosita: .toPandas() trae todos los datos al driver (a memoria local). Si el dataset es enorme → out of memory. Solo usa .toPandas() con datos ya agregados o pequeños.
Ejemplo completo:
from matplotlib import pyplot as plt
# 1. Agregar los datos con Spark (procesamiento distribuido)
data = spark.sql("""
SELECT Category, COUNT(ProductID) AS ProductCount
FROM products
GROUP BY Category
ORDER BY Category
""").toPandas() # <-- Convertimos a Pandas DESPUÉS de agregar
# 2. Limpiar cualquier plot previo
plt.clf()
# 3. Crear la figura con tamaño personalizado
fig = plt.figure(figsize=(12, 8))
# 4. Crear el bar chart
plt.bar(x=data['Category'], height=data['ProductCount'], color='orange')
# 5. Personalizar
plt.title('Product Counts by Category')
plt.xlabel('Category')
plt.ylabel('Products')
plt.grid(color='#95a5a6', linestyle='--', linewidth=2, axis='y', alpha=0.7)
plt.xticks(rotation=70) # Rotar etiquetas del eje X
# 6. Mostrar
plt.show()
15.3 · Seaborn (más bonito)
Seaborn está construido sobre Matplotlib pero con estilos más profesionales y bonitos:
import seaborn as sns
import matplotlib.pyplot as plt
# Setup del estilo
sns.set_theme(style="whitegrid")
# Convertir a Pandas
data = spark.sql("SELECT * FROM sales").toPandas()
# Ejemplo: scatter plot con color por categoría
sns.scatterplot(data=data, x="ListPrice", y="Sales", hue="Category")
plt.title("Precio vs Ventas por Categoría")
plt.show()
15.4 · Otras librerías útiles
Todas se instalan con %pip install X o vía environment:
Plotly: gráficos interactivos.
Bokeh: gráficos interactivos web-based.
Altair: gráficos declarativos.
15.5 · 🎯 Best practice
Regla del pulgar:
Haz agregación en Spark (distribuido, escalable).
Convierte a Pandas solo el resultado agregado (pequeño).
Visualiza con Matplotlib/Seaborn/Plotly.
NO al revés: no traigas todo a Pandas y luego agregues. Perderás la ventaja de Spark.
NO puede acceder a features distribuidas de Spark.
16.2 · Spark kernel
Ejecuta PySpark, SparkSQL, Scala, SparkR — todos con el mismo compute.
Multi-node: procesamiento distribuido.
Startup más lento (a menos que uses starter pool o live pool).
Ideal para: datasets grandes, ETL, Delta Lake, transformaciones distribuidas.
Puede acceder al catalog del lakehouse, Delta features, escritura a Tables.
16.3 · 🎯 Consideraciones para el examen
Microsoft es explícito en la doc: "The choice of notebook kernel isn't simply about cost or data size."
Factores importantes:
Factor
A favor de Python kernel
A favor de Spark kernel
Volumen de datos
Pocos MB - GB
Cientos de GB - TB
Crecimiento futuro
Estable
Va a crecer mucho
Uso de Delta Lake features
Bajo
Alto (schema evolution, time travel, etc.)
Concurrencia
Baja
Alta
Librerías Python
Sí (mejor compatibilidad)
Sí, con matices
Cost
Menor overhead por sesión
Mayor overhead pero escalable
16.4 · Reglas prácticas
Un notebook de exploración con pandas y matplotlib sobre 100 MB → Python kernel.
Un notebook de ETL bronze→silver con 500 GB de datos → Spark kernel.
Un notebook ML con 5 GB de features y XGBoost → puede ir en cualquiera, pero Python kernel + Pandas suele ser más simple.
Cualquier operación que escribe tablas Delta gestionadas del lakehouse → Spark kernel (Python puro no tiene acceso al catalog).
⚠️
17. Trampas típicas y confusiones frecuentes
Trampa 1: "El pool y el environment son lo mismo"
❌ Distintos. El pool es el compute (nodos, memoria). El environment es la config (runtime, libraries, Spark props). Un environment usa un pool.
Trampa 2: "Autoscale = Dynamic allocation"
❌ Autoscale escala nodos. Dynamic allocation escala executors. Son independientes y se pueden combinar.
Trampa 3: "El starter pool arranca al instante"
✅ Sí (~segundos), pero custom pools sin live mode tardan ~3 min. Custom live pools ~5 seg.
Trampa 4: "V-Order lo tengo que activar yo"
❌ Está activado por defecto en Fabric. Solo lo desactivas si tienes un motivo específico.
Trampa 5: "Native Execution Engine también está por defecto"
❌ NO. Hay que activarlo explícitamente con %%configure o en el environment.
Trampa 6: "En Fabric hay Spark 3.4"
❌ Fabric NO soporta Spark 3.4 ni anteriores. Runtimes actuales: 1.3 (Spark 3.5) y 2.0 (Spark 4.1).
Trampa 7: "Autotune está siempre disponible"
❌ Autotune solo funciona en Runtime 1.2 (retirado). No está en runtimes actuales.
Trampa 8: "%%sql corre en el SQL analytics endpoint"
❌ NO. %%sql en un notebook corre en el Spark SQL engine del pool, no en el SQL analytics endpoint. Son motores distintos.
Trampa 9: ".toPandas() es siempre seguro"
❌ Trae TODOS los datos al driver. Con datasets grandes → out of memory. Úsalo solo con datos ya agregados o pequeños.
Trampa 10: "Puedo particionar por cualquier columna"
❌ Particionar por columnas de alta cardinalidad genera miles de ficheros pequeños → peor performance. Usa columnas de baja cardinalidad.
Trampa 11: "Cuando leo una partición específica, la columna sigue en el DataFrame"
❌ La columna particionada desaparece del DataFrame cuando lees directamente una partición: spark.read.parquet("Files/data/Category=Road Bikes") → no verás la columna Category.
Trampa 12: "Todos los magics funcionan en pipelines"
❌ En pipelines solo funcionan: %%pyspark, %%spark, %%csharp, %%sql, %%configure. Otros fallan.
Trampa 13: "MSSparkUtils y NotebookUtils son distintos"
❌ Son el mismo paquete renombrado. mssparkutils seguirá funcionando por compatibilidad, pero notebookutils es el nuevo nombre oficial.
Trampa 14: "High concurrency mode se activa por defecto"
❌ Hay que activarlo manualmente en workspace settings.