★ DISPONIBILE PER FORMAZIONE E PROGETTI
enrico chiolo

Date stamping

Organizzare il warehouse per snapshot giornalieri append-only marcati con una colonna ds, così che ogni stato passato sia una semplice riga da filtrare.

Il date stamping è la tecnica di organizzare i dati di un data warehouse attorno a snapshot giornalieri append-only: ogni tabella ha una colonna ds (datestamp) che marca il giorno in cui i dati erano validi, ogni giorno si aggiungono righe nuove senza toccare le precedenti, e ogni analisi “al tempo T” diventa un semplice filtro sulla riga con datestamp T. Sahar Massachi lo presenta come il “one weird trick” centrale della serie “Stop using Slowly-changing Dimensions!” su DataExpert.io: il principio organizzatore che sostituisce le Slowly Changing Dimensions Type-2 e i loro join temporali.1

Il meccanismo

Ogni pipeline che parte dagli input fa due cose:1

  1. filtra l’input su WHERE ds={today}, prendendo solo il giorno che sta processando;
  2. appende l’output con lo stesso ds, aggiungendo righe marcate con il giorno invece di sovrascrivere.

L’append ha una precisazione tecnica: “you’re appending if today’s ds is empty and replacing if there is data in today’s ds”. I giorni diversi non si toccano mai; il giorno corrente è idempotente, e rieseguito sovrascrive solo se stesso.1

dim_users · UNA PARTIZIONE PER GIORNO ds=10-01 snapshot completo immutata ds=10-02 snapshot completo immutata ds=10-03 snapshot completo ds=oggi append mai overwrite WHERE ds='2024-10-03' Lo "stato al 3 ottobre" è una partizione, non un calcolo: il motore scansiona solo quel chunk.
Le tabelle datestampate crescono per append di snapshot giornalieri. Una query storica seleziona una partizione; le altre non vengono nemmeno lette.

Cosa risolve

Le conseguenze pratiche che la Parte 2 della serie elenca:1

  • Query storiche banali. Lo stato di ieri è WHERE ds={yesterday}, tre mesi fa è WHERE ds={tre mesi fa}. Per incrociare più tabelle storiche, ognuna filtra sulla propria ds e il join avviene su ds.
  • Backfill come bottone. La stessa pipeline del run giornaliero gestisce i backfill, e i giorni girano in parallelo (vedi backfilling).
  • Time machine incorporata. Ogni punto del passato è ricostruibile interrogando gli snapshot corrispondenti.
  • Bug correggibili. Si corregge la logica e si riprocessano le partizioni interessate: il dato corretto sovrascrive quello sbagliato.
  • Freshness evidente. Se l’ultima ds di una tabella risale a una settimana fa, è immediatamente chiaro che qualcosa non va, e spesso anche dove.
  • Storia gratis per le tabelle nuove. Una tabella creata oggi si popola all’indietro backfillando, ad esempio, 365 giorni.

Il fondamento teorico è il functional data engineering di Maxime Beauchemin: pipeline deterministiche dove il tempo è un dato esplicito, non uno stato nascosto. La condizione economica che lo rende possibile è il crollo dei costi di storage e compute dopo il 2015: ciò che rendeva necessarie le SCD-2 negli anni novanta non vale più.1

Il nome: ds, non date

La colonna si chiama tipicamente ds, abbreviazione di datestamp. Massachi avverte di non chiamarla date: creerebbe ambiguità tra la data di ingestione della riga e la data in cui l’evento è avvenuto, che è il significato naturale di “date” in una fact table. ds è corto, non invadente e non si confonde con le date di evento.1

Date stamp e date partition

I due termini si usano spesso in modo intercambiabile ma indicano cose diverse. Il date stamp è il concetto: marcare ogni riga con il giorno di validità. La date partition è l’implementazione fisica: il warehouse raggruppa tutte le righe con la stessa ds in uno stesso chunk, così una query WHERE ds='2025-01-15' scansiona solo quella partizione invece dell’intera tabella. Nei sistemi più vecchi la partizione era letteralmente una cartella; i cloud warehouse moderni la astraggono, ma l’effetto su velocità e costo resta, in particolare dove si paga per dato scansionato. Il concetto vale anche su motori che non partizionano fisicamente: ciò che conta è la colonna che permette di interrogare ogni punto della storia.1

In pratica

L’orchestratore, tipicamente Airflow, inietta la data come parametro templated: WHERE ds='{{ ds }}' nella sintassi Jinja di Airflow, o WHERE ds=@run_date con parameter binding. L’SQL del run di oggi e quello di un backfill di tre mesi fa sono identici, cambia solo il parametro: è questo che permette una sola codebase per entrambi i casi.1

Il precedente storico citato dalla serie è Facebook nei primi anni 2010: uno snapshot giornaliero del database MySQL di produzione, marcato con date stamp e copiato in Hive. La stessa architettura funziona oggi con Iceberg, Delta o Hudi.2

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
  • Sahar Massachi, The data warehouse setup no one taught you (Stop using Slowly-changing Dimensions! Part 1), DataExpert.io, 24 ottobre 2025. blog.dataexpert.io

Footnotes

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

  2. Massachi, Stop using SCD! Part 1, DataExpert.io, 2025.