Ogni tabella Delta in un lakehouse di Microsoft Fabric è composta da file Parquet più una cartella _delta_log. Il transaction log è la vera sorgente di verità: contiene i file JSON di commit (uno per transazione, numerati 00000000000000000000.json, ...001.json, ecc.) e i checkpoint Parquet generati periodicamente per non dover rileggere l’intera catena. Ogni commit registra quali file Parquet vengono aggiunti (add) e quali rimossi logicamente (remove). Nessun dato viene cancellato fisicamente da un DELETE o da un OVERWRITE: i file restano su OneLake e diventano semplicemente non referenziati dalla versione corrente. È esattamente questo che rende possibile il time travel.

Time travel: leggere il passato

Puoi interrogare una versione precedente in due modi, dallo Spark SQL del notebook:

SELECT * FROM sales VERSION AS OF 12;
SELECT * FROM sales TIMESTAMP AS OF '2026-07-15T08:30:00';

Per scoprire quali versioni esistono, l’operazione che le ha generate e l’utente che le ha eseguite si usa DESCRIBE HISTORY sales: è lo strumento di audit per eccellenza, perché mostra operation, operationParameters e operationMetrics (righe inserite, file scritti) di ogni commit.

Requisito Comando
Confrontare i dati prima/dopo un merge VERSION AS OF in una self-join
Riprodurre un report a una data certa TIMESTAMP AS OF
Capire chi ha sovrascritto la tabella DESCRIBE HISTORY
Annullare un carico sbagliato RESTORE TABLE ... TO VERSION AS OF

RESTORE: tornare indietro davvero

VERSION AS OF legge e basta. Per rimettere la tabella in uno stato precedente dopo una pipeline che ha caricato dati duplicati o un OVERWRITE errato serve:

RESTORE TABLE sales TO VERSION AS OF 11;
-- oppure
RESTORE TABLE sales TO TIMESTAMP AS OF '2026-07-16T22:00:00';

RESTORE non riscrive i dati: crea un nuovo commit che ripunta ai file della versione target. È quindi rapidissimo e, soprattutto, è a sua volta reversibile (la versione “sbagliata” resta nella history). Funziona solo se i file di quella versione esistono ancora — ed è qui che entra in gioco VACUUM.

VACUUM e la finestra di retention

VACUUM elimina fisicamente da OneLake i file Parquet non più referenziati dalla versione corrente e più vecchi della soglia di retention (default 7 giorni, controllata da delta.deletedFileRetentionDuration). Conseguenza diretta: VACUUM accorcia la finestra di time travel. Dopo un VACUUM con retention 7 giorni non puoi più fare RESTORE a una versione di tre settimane fa, anche se DESCRIBE HISTORY continua a mostrarla (la history è governata separatamente da delta.logRetentionDuration, default 30 giorni).

VACUUM sales RETAIN 168 HOURS;

Il rischio operativo concreto è abbassare la retention sotto le 168 ore su una tabella con job concorrenti: uno stream o una query lunga che sta ancora leggendo un file appena rimosso fallisce con errori di tipo file not found, e un semantic model Direct Lake può servire una versione non più materializzata finché non riesegue il framing. Delta blocca per default RETAIN 0 HOURS proprio con un controllo di sicurezza: disabilitarlo è ammesso solo in ambienti dove sei certo che nulla stia scrivendo o leggendo.

Manutenzione da UI del lakehouse

Nella Lakehouse explorer, clic destro su una tabella → Maintenance. Il pannello espone tre azioni combinabili in un unico Spark job:

  • OPTIMIZE — compatta i file piccoli (bin-compaction), problema tipico dopo molti micro-batch.
  • V-Order — riordino con ottimizzazione di lettura per il motore VertiPaq: fondamentale per le performance di Direct Lake e del SQL analytics endpoint.
  • VACUUM con soglia di retention configurabile.

La cadenza sensata è: OPTIMIZE + V-Order frequente sulle tabelle ad alto churn, VACUUM meno spesso e con retention allineata all’RPO concordato con il business.

Il warehouse è diverso

Nel Fabric Warehouse non esiste VACUUM: la retention (fino a 30 giorni) è gestita dal servizio. Il time travel si esprime a livello di statement con OPTION (FOR TIMESTAMP AS OF '2026-07-15T10:00:00.000') in UTC, e il recupero si fa tipicamente con una zero-copy clone table a un punto nel tempo, non con RESTORE. Il SQL analytics endpoint del lakehouse, invece, è in sola lettura: la manutenzione delle sue tabelle avviene sempre lato lakehouse.

Trappole tipiche d’esame

  • Una pipeline ha sovrascritto la tabella con dati sbagliati, serve ripristino immediato senza ricaricareRESTORE TABLE ... TO VERSION AS OF, non ri-eseguire l’ingestion né usare VERSION AS OF (che legge soltanto).
  • Requisito: garantire time travel a 30 giorni, ma si vuole ridurre lo storage → aumenta delta.deletedFileRetentionDuration (e logRetentionDuration) e schedula OPTIMIZE; non eseguire VACUUM con retention 7 giorni, che romperebbe il requisito.
  • Query Spark concorrenti falliscono con file mancanti dopo la manutenzione notturna → causa è VACUUM con retention troppo bassa; la risposta corretta è riportare la soglia ad almeno 168 ore, non riavviare il cluster.
  • Report Direct Lake lento per migliaia di file piccoli da ingestion in streaming → OPTIMIZE con V-Order dalla maintenance del lakehouse; VACUUM da solo non migliora le performance di lettura.
  • Recuperare una tabella del warehouse a ieri → clone/OPTION (FOR TIMESTAMP AS OF ...) entro i 30 giorni gestiti dal servizio; VACUUM e RESTORE non si applicano al warehouse.