Agregando e unindo dados com eficiência

Transformação de Dados com Spark SQL no Databricks

Disha Mukherjee

Lead Data Engineer

Três perguntas, um conjunto de dados limpo

recraft: half: Um analista de dados revisando gráficos coloridos e relatórios de negócios em várias telas, isolado em fundo transparente

 

$$

  • Quais categorias geram mais receita?
  • Quem são os melhores clientes?
  • Como enriquecer os resultados com o contexto de departamentos?
Transformação de Dados com Spark SQL no Databricks

Como funcionam groupBy() e agg()

 

$$

  • groupBy() - particiona linhas pela coluna-chave
  • agg() - aplica funções a cada grupo em paralelo
  • Ambas são preguiçosas - uma ação dispara o cálculo
  • Uma chamada agg() = um varrimento de dados

recraft: half: Linhas coloridas de dados divididas em três grupos separados com rótulos, com um valor total calculado abaixo de cada grupo, isolado em fundo transparente

Transformação de Dados com Spark SQL no Databricks

Receita por categoria - 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())
)
Transformação de Dados com Spark SQL no Databricks

Receita por categoria - saída

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       |
+-----------+-----------------+-----------------+---------------+
Transformação de Dados com Spark SQL no Databricks

Enriquecendo com uma tabela de dimensão

recraft: half: Duas tabelas de banco de dados conectadas por um elo ou ponte brilhante, isoladas em fundo transparente

$$

+-----------+----------+
|Category   |Department|
+-----------+----------+
|Clothing   |Retail    |
|Dining     |Food      |
|Electronics|Tech      |
|Groceries  |Food      |
|Savings    |Finance   |
+-----------+----------+
Transformação de Dados com Spark SQL no Databricks

Left join padrão

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          |
+-----------+-----------+----------+------------------+
Transformação de Dados com Spark SQL no Databricks

O custo oculto - shuffle

recraft: half: Pacotes de dados fluindo por uma rede de servidores e nós conectados com setas indicando o movimento, isolado em fundo transparente

 

  • Chaves correspondentes devem ficar na mesma máquina
  • O Spark envia linhas pela rede para alinhar
  • Shuffle = gargalo em escala
Transformação de Dados com Spark SQL no Databricks

Spark UI

recraft: full: Um painel escuro de monitoramento analítico com gráficos de barras horizontais coloridos mostrando estágios de jobs, barras de progresso e métricas de throughput de dados, isolado em fundo transparente

 

  • Jobs e Stages - acompanham o que rodou e por quanto tempo
  • Shuffle Read/Write - veja quanto dado se moveu
  • Útil para diagnosticar gargalos de pipeline
Transformação de Dados com Spark SQL no Databricks

Lendo o plano de consulta com .explain()

df_joined.explain(mode="formatted")
...
+- PhotonBroadcastHashJoin LeftOuter (18)
   :- ...
   +- PhotonShuffleExchangeSource (17)
      +- PhotonShuffleMapStage (16)
         +- PhotonShuffleExchangeSink (15)
            +- LocalTableScan (13)
...
  • .explain() - inspecione o plano de execução
  • Nós 15 e 16 - sem routing Arguments registrados
Transformação de Dados com Spark SQL no Databricks

Broadcast join - a correção

# Wrap the small table in 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
Transformação de Dados com Spark SQL no Databricks

Antes e depois - verificando o plano

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]
  • Tabela de dimensão tem instruções de roteamento
  • A tabela grande df_valid não se move
  • Uma mudança = minutos viram segundos em escala
Transformação de Dados com Spark SQL no Databricks

Vamos praticar!

Transformação de Dados com Spark SQL no Databricks

Preparing Video For Download...