Снимки (snapshots) — это фундаментальная концепция Apache Iceberg, обеспечивающая поддержку транзакций и версионирования данных в Data Lake.

Каждый snapshot представляет собой полное, согласованное состояние таблицы на определённый момент времени.

  • Snapshot включает ссылки на конкретные наборы файлов данных и соответствующие метаданные.
  • Snapshot неизменяем (immutable). Любое изменение таблицы создаёт новый snapshot.

🔍 Как устроены snapshot’ы в Iceberg?

Внутренне Iceberg хранит таблицу как последовательность snapshot’ов.
Каждый snapshot содержит:

  • Ссылки на файлы данных (например, Parquet или ORC).
  • Манифесты (Manifest files), описывающие добавленные и удалённые файлы.
  • Метаданные (структуру таблицы, partitioning и другую служебную информацию).
Iceberg Table
├── Metadata
│   ├── Snapshot 100 (текущее состояние)
│   │   ├── Manifest 1 → data-file-1.parquet, data-file-2.parquet
│   │   └── Manifest 2 → data-file-3.parquet
│   │
│   ├── Snapshot 99 (предыдущее состояние)
│   │   └── Manifest 3 → data-file-1.parquet, data-file-2.parquet
│   │
│   └── Snapshot 98 (более старое состояние)
│       └── Manifest 4 → data-file-1.parquet
│
└── Data Files (Parquet, ORC, Avro)
    ├── data-file-1.parquet
    ├── data-file-2.parquet
    └── data-file-3.parquet


🕑 Как snapshot’ы обеспечивают поддержку Time-travel queries?

Iceberg сохраняет историю всех snapshot’ов, что позволяет:

  • Query as of timestamp — запросить данные по состоянию на конкретную дату и время.
  • Query as of snapshot-id — запросить таблицу по конкретному идентификатору snapshot’а.
  • Откат таблицы к предыдущему состоянию.

Таким образом, вы можете легко просматривать состояние данных в прошлом.


📌 Примеры Time-travel запросов в Iceberg

🔹 Запрос по snapshot-id

SELECT * FROM my_table VERSION AS OF 123456789;

Здесь 123456789 — идентификатор конкретного snapshot’а таблицы.

🔹 Запрос по timestamp

SELECT * FROM my_table TIMESTAMP AS OF '2024-12-31 23:59:59';

Вы получите состояние таблицы ровно на указанное время.


📍 Как создаются snapshot’ы в Iceberg?

Каждое изменение таблицы (insert, update, delete) порождает новый snapshot:

  • Добавление данных (append) → новый snapshot.
  • Удаление данных (delete) → новый snapshot.
  • Обновление данных (update) → новый snapshot.

Например (Spark API):

table.newAppend()
    .appendFile(dataFile) // добавляем файл
    .commit()             // создаётся новый snapshot
 

🎯 Преимущества snapshot’ов и time-travel:

  • ACID-транзакции:
    Снимки гарантируют атомарность и согласованность каждого состояния таблицы.

  • Эффективное версионирование данных:
    Iceberg прозрачно управляет версиями данных и позволяет легко откатиться.

  • Отладка и аналитика исторических данных:
    Возможность проводить аналитику и расследования на любом состоянии данных в прошлом.

  • Восстановление после ошибок:
    Возможность вернуть таблицу к состоянию до ошибочной транзакции.


📊 Пример применения snapshot’ов (реальный сценарий)

Допустим, вы загрузили неверные данные и хотите откатиться:

  1. Узнаёте идентификатор последнего правильного snapshot’а:

sql

Copy

SELECT snapshot_id, committed_at FROM my_table.snapshots ORDER BY committed_at DESC;

snapshot_idcommitted_at
1234567902024-12-01 11:00:00
1234567892024-11-30 11:00:00
  1. Откатываетесь к нужному snapshot’у:

scala

Copy

table.manageSnapshots() .rollbackTo(123456789) .commit()

✅ Таблица восстановлена до стабильного состояния!


🚀 Краткий итог (резюме)

СвойствоОписание в Apache Iceberg
SnapshotImmutable-состояние таблицы в момент времени
ACID транзакцииКаждый snapshot — согласованная транзакция
Time-travelЗапрос состояния таблицы на любое время
ВерсионированиеВозможность отката и управления версиями

Таким образом, snapshot’ы являются фундаментальным механизмом Apache Iceberg, обеспечивающим мощную функциональность ACID-транзакций и time-travel в Data Lake.