
Partitioning strategies on data lakes
Designing optimal partitions for query engines on S3: trade-offs and established patterns.
What you will learn
- Scegliere la chiave di partizione dai filtri ricorrenti delle query
- Dimensionare le partizioni tra 100 e 500 MB in Parquet
- Evolvere la granularità con partizioni aggiuntive o compattazione dei dati vecchi
Partitioning strategies on data lakes
Questa lezione, come le altre del binario ml-tabellare, affronta un tema tecnico con una sola cosa in mente: capire quale layout cambia costo e latenza delle analisi. Partizionare un data lake significa disporre i file su S3 in modo che le query leggano solo i dati necessari. Una tabella di eventi può essere interrogata per giorno, paese, cliente o campagna. Se la partizioni male, ogni query scansiona troppo. Se esageri, ottieni migliaia di partizioni minuscole che appesantiscono i metadati.
L’idea in una frase
Partizionare un data lake significa disporre i file su S3 secondo le colonne filtrate dalle query ricorrenti, così ogni analisi legge solo le partizioni necessarie.
Come procedere, passo dopo passo
- Elenca le query più frequenti e pesanti con i filtri presenti nel
WHERE. - Stima la cardinalità di ogni colonna candidata e il numero di partizioni generate.
- Scegli la colonna dei filtri ricorrenti che mantiene le partizioni tra 100 e 500 MB in
Parquet. - Scrivi il layout nel path e misura i GB scansionati prima e dopo il cambio.
- Compatta i file piccoli e rivedi la granularità quando i volumi cambiano.
Il problema che il partizionamento risolve
Il punto non è la teoria del partizionamento in astratto: è decidere come strutturare i dati quando il team ha query ricorrenti, volumi in crescita e un budget di scansione da rispettare. Una partizione utile riduce i dati letti. Una partizione eccessiva aumenta i metadati, moltiplica i file piccoli e complica le operazioni. La lezione insegna a disegnare il layout fisico dalle query reali, non dall’intuizione su quale colonna sembri più naturale.
Come ragionare prima di scegliere una colonna
Conviene seguire una sequenza di domande, in cui ogni passaggio chiarisce il costo di una scelta sbagliata.
| Step | Question to ask | Expected output |
|---|---|---|
| Decision | Quale layout fisico stiamo scegliendo? | Scelta esplicita |
| Signal | Quali query sono più frequenti e più pesanti? | Pattern di filtro osservato |
| Baseline | Quanti dati scansiona oggi una query tipica? | Costo di riferimento |
| Vincolo | Quante partizioni genera questa colonna? | Cardinalità sostenibile |
| Action | Quale colonna mettiamo nel path? | Layout verificabile |
Questa griglia evita di ridurre il partizionamento a un rituale. Ogni riga deve collegarsi a un costo concreto: GB scansionati, numero di file e latenza della query.
Mettere a fuoco le assunzioni
Conviene rendere esplicite le scelte, così uno stakeholder può discutere il criterio invece di fidarsi del risultato per autorità. L’unità di ragionamento è la partizione, cioè il prefisso che raggruppa un insieme di file Parquet. Il segnale osservato sono i GB scansionati e il tempo di risposta. Il rischio residuo è scegliere una colonna molto granulare solo perché disponibile, generando partizioni piccole che peggiorano tutto.
| Element | Operational Definition | Controllo minimo |
|---|---|---|
| Unit of analysis | La partizione e i file che contiene | Path, formato, dimensione |
| Variabile osservata | GB scansionati e latenza | Misura ripetibile sulla stessa query |
| Baseline | Costo della query prima del cambio layout | Periodo o tabella di confronto |
| Soglia decisionale | Dimensione di partizione accettabile | Criterio scritto prima della misura |
| Rischio residuo | Troppe partizioni o partizioni troppo grandi | Conteggio file e revisione |
The Golden Rule of Partitions
Partiziona per la colonna che filtri nel WHERE delle query più frequenti e pesanti. Per un lake di eventi conviene year/month/day se le query filtrano sempre per data. Per un lake di clienti segmentato per paese conviene country se le query filtrano sempre per quella dimensione. La colonna giusta non è la più dettagliata, ma quella che compare nei filtri ricorrenti.
The ideal size of a partition
Una partizione dovrebbe contenere tra 100 e 500 MB di dati in formato Parquet. Sotto i 100 MB ottieni troppi file piccoli e un overhead elevato sulle operazioni S3 LIST. Sopra 1 GB il partition pruning diventa meno efficace e la query scansiona dati non necessari.
Un calcolo rapido aiuta a scegliere la granularità. Se generi 100 GB al giorno di eventi, la partizione per day è quella giusta: circa 100 MB se Parquet comprime a 10x. Se generi 100 MB al giorno, conviene partizionare per month, circa 3 GB al mese, oppure per week.
Evoluzione delle partizioni nel tempo
I dati crescono e la granularità di ieri può non bastare domani. Ci sono due pattern principali. Il primo è aggiungere partizioni: si passa da year/month a year/month/day quando il volume aumenta, i nuovi dati usano le partizioni più granulari e i vecchi restano come sono. Athena e Trino gestiscono partizioni eterogenee senza problemi. Il secondo è compattare le partizioni vecchie: i dati di tre anni fa, ormai a basso volume residuo, passano da day a month con un job Spark or a Athena CTAS.
Un caso che mostra l’errore opposto
A table is partitioned by user_id perché sembra granulare e quindi efficiente. Il risultato è opposto: milioni di partizioni minuscole, metadati ingestibili e query più lente. Il caso mostra che la partizione deve seguire i filtri ricorrenti e una cardinalità sostenibile, non la colonna con più valori distinti.
| Observed evidence | Cautious interpretation | Recommended action |
|---|---|---|
| La query scansiona più del previsto | Forse il filtro non sfrutta la partizione | Verificare path e predicate pushdown |
| Migliaia di file da pochi KB | Granularità troppo alta | Compattare o salire di livello |
| Il costo cresce col volume | Layout non scala | Rivedere la chiave di partizione |
Typical mistake to avoid
L’errore più comune è scegliere la chiave di partizione per intuizione invece che dai pattern di query. Succede quando si parte dalla colonna più dettagliata o più importante, senza guardare quali filtri compaiono davvero nel WHERE. La domanda di controllo è semplice: quale query reale diventa più economica con questo layout? Se non sai rispondere, manca il collegamento tra struttura fisica e uso effettivo.
Verdetto: per query filtrate per data usa year/month/day, per query filtrate per paese usa country, e non partizionare mai per chiavi ad alta cardinalità come user_id.
References
- AWS. (2024). “Top 10 Performance Tuning Tips for Amazon Athena.” AWS Big Data Blog.
- Databricks. (2024). “Delta Lake Best Practices.” databricks.com.
Il caso Amazon Athena
Amazon Athena, lanciata da AWS nel 2016, fattura le interrogazioni in base ai TB scansionati, con un prezzo pubblico di cinque dollari per TB. Proprio per questo la documentazione AWS indica il partition pruning come prima ottimizzazione: una clausola sui filtri di partizione evita di leggere il resto della tabella. Una query che senza partizioni scansiona l’intero storico può così leggere solo i mesi richiesti, con costo e latenza proporzionalmente inferiori. Il caso mostra la tesi della lezione: il layout fisico decide la fattura prima ancora del motore.
Domande per verificare quello che hai capito
- Quale query ricorrente vuoi rendere più economica con il nuovo layout?
- Quale colonna del
WHEREusi come chiave di partizione e perché? - Quanti GB scansiona oggi quella query prima del cambio?
- Quante partizioni genera la colonna scelta e quale dimensione media attendi?
- Quando ricontrolli file piccoli e granularità dopo il rollout?
Bloccato su questo argomento o vuoi applicarlo al tuo caso? Prenota una call di 15 minuti con un analista esperto.
Related Path
Lessons to read together
Questi collegamenti portano la lezione dentro il resto del corso: basi da riprendere, passaggi successivi e connessioni tematiche tra moduli.