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 ricaricare →
RESTORE TABLE ... TO VERSION AS OF, non ri-eseguire l’ingestion né usareVERSION AS OF(che legge soltanto). - Requisito: garantire time travel a 30 giorni, ma si vuole ridurre lo storage → aumenta
delta.deletedFileRetentionDuration(elogRetentionDuration) 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 eRESTOREnon si applicano al warehouse.