// data & ai · giornale tecnico MILANO ● LIVE 00:00:00

PySpark oltre le basi: partizioni, shuffle, join e piani di esecuzione

Passare a un livello intermedio in PySpark significa soprattutto capire il movimento dei dati: partizioni, shuffle, join, caching, layout Parquet e piani di esecuzione.

Una volta imparate le basi di PySpark (creare una SparkSession, caricare DataFrame, pulire colonne, fare join e scrivere Parquet) arrivano le domande difficili: perché un job diventa lento, perché un groupBy() ci mette più del previsto, perché PySpark scrive tanti file, quando conviene fare cache. Il filo conduttore di questo tutorial di Thomas Reid è uno: il livello intermedio in PySpark è soprattutto capire il movimento dei dati. Quando questa idea diventa chiara, le prestazioni smettono di sembrare casuali.

Partizioni e shuffle

Un DataFrame non è un blocco unico: PySpark lo divide in partizioni, chunk elaborati in parallelo. Troppe poche partizioni non sfruttano tutti i core, troppe fanno perdere tempo nella gestione di task minuscoli. Si regolano con repartition() (ridistribuisce i dati, con un costo) e coalesce() (riduce le partizioni con meno movimento, utile per scrivere meno file). Lo shuffle è la ridistribuzione dei dati tra partizioni: operazioni come groupBy(), join(), distinct(), orderBy() e repartition() lo provocano. Non sono da evitare a priori, ma sono costose. Una buona abitudine è filtrare e selezionare le colonne prima delle operazioni costose, così c’è meno dati da spostare.

Join e piani di esecuzione

I join meritano attenzione perché far incontrare chiavi corrispondenti spesso richiede movimento. Tre accorgimenti: allineare i tipi delle join key (facendo cast se serve), tenere solo le colonne necessarie e filtrare presto, e valutare il broadcast delle piccole lookup table, che PySpark copia su ogni worker invece di fare shuffle di entrambi i dataset. Grazie alla lazy evaluation, PySpark costruisce un piano prima di eseguire: df.explain(“formatted”) lo mostra. Vale la pena riconoscere pochi indizi, Exchange su tutti, che segnala uno shuffle; Scan, Filter, Project, SortMergeJoin, BroadcastHashJoin e HashAggregate raccontano il resto. Anche la UI su localhost:4040 aiuta a vedere quali stage sono lenti.

Caching, Parquet e trappole comuni

Il caching non è un pulsante magico: conviene solo quando un DataFrame è costoso da creare e viene riusato più volte nella stessa sessione, e va materializzato con un’action come count(). Scrivere Parquet con partitionBy() su colonne di uso frequente (year, month, region) abilita il partition pruning in lettura, ma non si deve partizionare per colonne ad alta cardinalità come transaction_id. Meglio le funzioni built-in rispetto alle UDF Python, più difficili da ottimizzare. Tra le trappole con dati grandi: collect() che scarica tutto sul driver, count() usato troppo spesso, orderBy() globale (spesso basta limit(10) per una top-k) e i loop Python al posto di operazioni sul DataFrame.

  • Riconoscere partizioni, shuffle e join rende molto più facile diagnosticare i job lenti.
  • Filtrare presto e ridurre le colonne prima dei join limita il costo dello shuffle.
  • Il layout dei file Parquet incide su lettura e scrittura tanto quanto il codice.

Fonte: PySpark for Beginners: Building Intermediate-Level Skills — https://towardsdatascience.com/pyspark-for-beginners-building-intermediate-level-skills/

Condividi X Facebook LinkedIn WhatsApp Email

// scritto da

Fernando

Hai qualcosa da aggiungere? Unisciti alla discussione.

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Altri dell'autore

dalla stessa firma