PySpark optimizado: particionamento, caching e tuning para performance
João Barros
27 de May de 2025
2 min de leitura
O Apache Spark é poderoso mas exige atenção a detalhes de configuração e design para correr eficientemente em larga escala. Pequenos erros de particionamento ou joins mal planeados podem multiplicar o tempo de execução por 10x.
Particionamento
O número de partições define o paralelismo. Demasiado poucas partições subaproveitam o cluster; demasiadas criam overhead de shuffle.
# Ver número de partições actuais
print(df.rdd.getNumPartitions())
# Reparticionar (shuffle completo — caro)
df = df.repartition(200, "pais")
# Coalesce (sem shuffle — apenas reduz)
df = df.coalesce(50)
Caching estratégico
# Cache em memória (mais rápido, pode ser evicted)
df_filtrado = df.filter(col("ano") == 2024).cache()
df_filtrado.count() # materializa o cache
# Persist com nível explícito
from pyspark import StorageLevel
df_filtrado.persist(StorageLevel.MEMORY_AND_DISK_SER)
# Libertar quando já não é necessário
df_filtrado.unpersist()
Broadcast Join para tabelas pequenas
from pyspark.sql.functions import broadcast
# Força broadcast da dimensão pequena — evita shuffle na tabela grande
df_result = df_factos.join(broadcast(df_dim_produto), "id_produto")
Evitar shuffles desnecessários
# Mau: groupBy em colunas de alta cardinalidade sem necessidade
df.groupBy("id_cliente", "id_produto").agg(sum("valor"))
# Melhor: pré-agregar antes de joins
df_agg = df.groupBy("id_produto").agg(sum("valor").alias("total"))
df_agg.join(df_dim_produto, "id_produto")
Configurações essenciais
spark.conf.set("spark.sql.shuffle.partitions", "200") # padrão 200
spark.conf.set("spark.sql.adaptive.enabled", "true") # AQE — auto-tuning
spark.conf.set("spark.sql.adaptive.coalescePartitions.enabled", "true")
Conclusão
Performance em Spark é uma combinação de bom design (particionamento, evitar shuffles desnecessários, broadcast de dimensões pequenas) com configuração adequada (AQE, shuffle partitions). Use o Spark UI para identificar stages lentos e skew de dados antes de optimizar.