Снимки (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’ов (реальный сценарий)
Допустим, вы загрузили неверные данные и хотите откатиться:
- Узнаёте идентификатор последнего правильного snapshot’а:
sql
Copy
SELECT snapshot_id, committed_at FROM my_table.snapshots ORDER BY committed_at DESC;
snapshot_id | committed_at |
---|---|
123456790 | 2024-12-01 11:00:00 |
123456789 | 2024-11-30 11:00:00 |
… | … |
- Откатываетесь к нужному snapshot’у:
scala
Copy
table.manageSnapshots() .rollbackTo(123456789) .commit()
✅ Таблица восстановлена до стабильного состояния!
🚀 Краткий итог (резюме)
Свойство | Описание в Apache Iceberg |
---|---|
Snapshot | Immutable-состояние таблицы в момент времени |
ACID транзакции | Каждый snapshot — согласованная транзакция |
Time-travel | Запрос состояния таблицы на любое время |
Версионирование | Возможность отката и управления версиями |
Таким образом, snapshot’ы являются фундаментальным механизмом Apache Iceberg, обеспечивающим мощную функциональность ACID-транзакций и time-travel в Data Lake.