Agregar y unir datos de forma eficiente

Transformación de datos con Spark SQL en Databricks

Disha Mukherjee

Lead Data Engineer

Tres preguntas, un conjunto de datos limpio

recraft: half: Un/a analista de datos revisando gráficos coloridos e informes de negocio en varias pantallas, aislado sobre fondo transparente

 

$$

  • ¿Qué categorías generan más ingresos?
  • ¿Quiénes son l@s mejores clientes?
  • ¿Cómo enriquecer resultados con el contexto de departamento?
Transformación de datos con Spark SQL en Databricks

Cómo funcionan groupBy() y agg()

 

$$

  • groupBy() - particiona filas por la columna clave
  • agg() - aplica funciones a cada grupo en paralelo
  • Ambas son perezosas: una acción dispara el cómputo
  • Una llamada a agg() = un escaneo de datos

recraft: half: Filas de datos coloridas divididas en tres grupos etiquetados con un valor total calculado bajo cada grupo, aislado sobre fondo transparente

Transformación de datos con Spark SQL en Databricks

Ingresos por categoría: código

category_revenue = (
    df_valid
    .groupBy("Category")

.agg( F.round(F.sum("Transaction_Amount"), 2).alias("total_revenue"), F.count("Transaction_Amount").alias("transaction_count"), F.round(F.avg("Transaction_Amount"), 2).alias("avg_transaction"), )
.orderBy(F.col("total_revenue").desc())
)
Transformación de datos con Spark SQL en Databricks

Ingresos por categoría: salida

category_revenue.show(truncate=False)
+-----------+-----------------+-----------------+---------------+
|Category   |total_revenue    |transaction_count|avg_transaction|
+-----------+-----------------+-----------------+---------------+
|Clothing   |338266605.24     |6742             |50173.04       |
|Dining     |337631718.64     |6719             |50250.29       |
|Electronics|331102843.72     |6614             |50060.91       |
|Savings    |329346609.07     |6596             |49931.26       |
|Groceries  |329003451.57     |6537             |50329.43       |
|Unknown    |880591.27        |15               |58706.08       |
+-----------+-----------------+-----------------+---------------+
Transformación de datos con Spark SQL en Databricks

Enriquecer con una tabla de dimensión

recraft: half: Dos tablas de base de datos conectadas por un enlace o puente luminoso, aisladas sobre fondo transparente

$$

+-----------+----------+
|Category   |Department|
+-----------+----------+
|Clothing   |Retail    |
|Dining     |Food      |
|Electronics|Tech      |
|Groceries  |Food      |
|Savings    |Finance   |
+-----------+----------+
Transformación de datos con Spark SQL en Databricks

Left join estándar

df_joined = df_valid.join(df_dim, on="Category", how="left")

df_joined.select( "Customer_ID", "Category", "Department", "Transaction_Amount" ).show(5, truncate=False)
+-----------+-----------+----------+------------------+
|Customer_ID|Category   |Department|Transaction_Amount|
+-----------+-----------+----------+------------------+
|CUST003    |Electronics|Tech      |5752.36           |
|CUST009    |Clothing   |Retail    |28959.12          |
|CUST010    |Savings    |Finance   |72098.18          |
|CUST011    |Savings    |Finance   |49771.05          |
|CUST020    |Groceries  |Food      |69825.14          |
+-----------+-----------+----------+------------------+
Transformación de datos con Spark SQL en Databricks

El coste oculto: shuffle

recraft: half: Paquetes de datos fluyendo por una red de servidores y nodos conectados con flechas que muestran el movimiento, aislado sobre fondo transparente

 

  • Las claves coincidentes deben ir a la misma máquina
  • Spark envía filas por la red para alinearlas
  • Shuffle = cuello de botella a gran escala
Transformación de datos con Spark SQL en Databricks

Spark UI

recraft: full: Un panel de monitorización analítica oscuro con barras horizontales coloridas que muestran etapas de jobs, barras de progreso y métricas de rendimiento de datos, aislado sobre fondo transparente

 

  • Jobs y Stages: qué se ejecutó y cuánto duró
  • Shuffle Read/Write: cuántos datos se movieron
  • Útil para diagnosticar cuellos de botella en la canalización
Transformación de datos con Spark SQL en Databricks

Leer el plan de consulta con .explain()

df_joined.explain(mode="formatted")
...
+- PhotonBroadcastHashJoin LeftOuter (18)
   :- ...
   +- PhotonShuffleExchangeSource (17)
      +- PhotonShuffleMapStage (16)
         +- PhotonShuffleExchangeSink (15)
            +- LocalTableScan (13)
...
  • .explain() - inspecciona el plan de ejecución
  • Nodos 15 y 16: sin routing Arguments registrados
Transformación de datos con Spark SQL en Databricks

Broadcast join: la solución

# Envuelve la tabla pequeña con F.broadcast()
df_broadcast = df_valid.join(
    F.broadcast(df_dim),
    on="Category",
    how="left"
)

print(f"Broadcast joined rows: {df_broadcast.count():,}")
Broadcast joined rows: 33,223
Transformación de datos con Spark SQL en Databricks

Antes y después: verificar el plan

df_broadcast.explain(mode="formatted")
+- PhotonBroadcastHashJoin LeftOuter (18)
   :- ...
   +- PhotonShuffleExchangeSource (17)
      +- PhotonShuffleMapStage (16)
         +- PhotonShuffleExchangeSink (15)
            +- LocalTableScan (13)
...            
(15) PhotonShuffleExchangeSink
Arguments: SinglePartition
(16) PhotonShuffleMapStage
Arguments: EXECUTOR_BROADCAST, [id=#11839]
  • La tabla de dimensión tiene instrucciones de enrutado
  • La tabla grande df_valid no se mueve
  • Un cambio = de minutos a segundos a escala
Transformación de datos con Spark SQL en Databricks

¡Vamos a practicar!

Transformación de datos con Spark SQL en Databricks

Preparing Video For Download...