★ DISPONIBILE PER FORMAZIONE E PROGETTI
enrico chiolo

Backfilling

Riprocessare dati storici attraverso una pipeline: un incubo sequenziale con le SCD-2, un bottone con le tabelle datestampate.

In data engineering backfillare significa riprocessare dati storici, giorni, mesi o anni passati, attraverso una pipeline. I casi tipici: si scopre un bug nella logica di trasformazione, si crea una tabella nuova e la si vuole popolare con la storia pregressa, o un cambiamento a monte (una correzione in dim_users) deve propagarsi alle tabelle che ne dipendono. Sahar Massachi, nella Parte 2 della serie “Stop using Slowly-changing Dimensions!” su DataExpert.io, usa il backfilling come banco di prova per confrontare le Slowly Changing Dimensions e il date stamping: con le prime è un’operazione sequenziale con codebase dedicata, con il secondo è la stessa pipeline del run giornaliero eseguita in parallelo.1

Il caso SCD-2: la catena sequenziale

Con le SCD Type-2 e le colonne valid_from/valid_to, ogni giorno di pipeline dipende dallo stato del giorno precedente: il giorno 15 aggiorna righe scritte il giorno 14. Backfillare novembre significa rieseguire il primo novembre partendo dallo stato del 31 ottobre, aspettare che finisca, rieseguire il 2 novembre, e così via per trenta giorni in fila. In Airflow è il comportamento del flag depends_on_past=True: ogni esecuzione è bloccata finché la precedente non completa, e se il giorno 18 fallisce si ricomincia. Su un backfill di cinque anni, stima Massachi, si passa da “sei volte più lento” a “centinaia di volte più lento”.1

C’è un secondo costo: il backfill SCD-2 richiede SQL diverso dal run giornaliero, perché deve chiudere le righe vecchie, inserire le nuove, gestire is_current e il caso di una riga cambiata più volte dentro la finestra. Si finisce con due codebase da mantenere in parallelo, e ogni modifica alla logica giornaliera va replicata in quella di backfill. E se il dato sorgente è uscito dalla finestra di retention, con SCD-2 non si può backfillare affatto: bisogna ricostruire la tabella da zero, cosa che richiede, per l’appunto, snapshot datestampati.1

Il caso datestampato: il bottone

Con il date stamping la pipeline di un giorno ha bisogno solo di due cose: input filtrati sulla ds di quel giorno e output scritto nella stessa ds. Il 15 novembre non dipende dal 14: dipende solo dallo snapshot del 15. Ne segue che tutti i giorni di un backfill partono in parallelo, fino ai limiti di concorrenza del DAG, ognuno legge e scrive la propria partizione senza coordinarsi con gli altri, e il mese intero finisce nel tempo di un giorno solo. Lo stesso SQL del run giornaliero gestisce il backfill: l’orchestratore inietta la data come parametro (WHERE ds='{{ ds }}' in Airflow) e la pipeline non sa se sta processando oggi o tre mesi fa.1

SCD-2 · SEQUENZIALE 1 nov 2 nov 3 nov ··· 30 nov Ogni giorno aspetta il precedente. Se il 18 fallisce, si ricomincia. SQL dedicato al backfill. DATE STAMPING · PARALLELO backfill nov ds=1 nov ds=2 nov ds=3 nov ··· ds=30 nov Stesso SQL del daily run WHERE ds='{{ ds }}' Trenta giorni indipendenti partono insieme: il mese finisce nel tempo di un giorno.
Lo stesso backfill di novembre nei due modelli. Con SCD-2 i giorni si aspettano in catena; con il date stamping ogni giorno legge e scrive la propria partizione, in parallelo.

Cosa rende possibile

  • Tabelle nuove con storia. Una dim_users_enriched creata oggi si popola con l’ultimo anno backfillando 365 giorni: i dati raw ci sono già, aspettano.1
  • Bug nei dati storici correggibili. Si corregge la logica, si backfilla l’intervallo interessato, il dato nuovo sovrascrive le partizioni sbagliate.1
  • Propagazione dei cambiamenti a monte. Una correzione in dim_users scende a valle backfillando in parallelo le date interessate di tutte le tabelle dipendenti, e il warehouse resta coerente.1

La condizione è che le pipeline siano idempotenti, nel senso del functional data engineering: eseguite una volta o mille, dato lo stesso giorno di input, producono lo stesso output, senza stato nascosto né logica “corrente contro storico”.1

L’anti-pattern

La catena si ricrea, anche senza flag espliciti, quando una tabella dipende dalla partizione del giorno precedente di se stessa: se dim_users di oggi richiede dim_users di ieri, backfillare 90 giorni significa 90 esecuzioni in sequenza. Massachi prescrive depends_on_past=False per la maggior parte delle pipeline datestampate, con un’eccezione legittima: le metriche cumulative (il totale storico dei post di un utente), dove la dipendenza dal giorno precedente è strutturale e ricalcolare da raw ogni giorno costerebbe l’intera storia.1

Voci correlate

Bibliografia e sitografia

  • Sahar Massachi, SCD-2 considered harmful! (Stop using Slowly-changing Dimensions! Part 2), DataExpert.io, 4 novembre 2025. blog.dataexpert.io

Footnotes

  1. Massachi, SCD-2 considered harmful! Part 2, DataExpert.io, 2025. 2 3 4 5 6 7 8 9