Iceberg time travel на собеседовании Data Engineer

Проверь себя · 1/3разбор после ответа
Вы сортируете товары по величине скидки discount по убыванию. Поле discount может быть NULL (скидки нет). Чтобы товары без скидки всегда оказывались внизу независимо от настроек СУБД, какой вариант сортировки выбрать?

Почему time travel спрашивают

Time travel — одна из главных фич, ради которых команды переезжают с обычных Hive-таблиц на Apache Iceberg. Она позволяет прочитать таблицу такой, какой она была в любой момент прошлого: неделю назад, до вчерашней перезаписи, в конкретную дату для отчёта регулятору. На собесе Data Engineer это любимая тема, потому что за ней стоит понимание всей архитектуры Iceberg — метаданных, снапшотов и того, чем табличный формат отличается от «просто папки с parquet-файлами».

Типичная развилка на интервью: кандидат думает, что time travel — это про бэкапы. Это не так. Time travel работает поверх обычных данных таблицы за счёт неизменяемых снапшотов, и стоит понимать, откуда он берётся и как долго остаётся доступным.

Snapshots

Каждая операция записи в таблицу (INSERT, UPDATE, DELETE, MERGE, компакция) создаёт новый snapshot — неизменяемый (immutable) слепок состояния таблицы. Старые снапшоты не переписываются: Iceberg просто добавляет новый и переключает на него указатель текущего состояния. Именно поэтому таблицу можно «отмотать» назад — прошлые снапшоты физически лежат в метаданных.

Посмотреть историю можно через служебную таблицу метаданных:

SELECT * FROM iceberg.events.snapshots;
-- покажет snapshot_id, parent_id, operation (append/overwrite/delete),
-- committed_at и manifest-файлы каждого снапшота

Каждый снапшот ссылается на набор manifest-файлов, а те — на конкретные data-файлы. Так Iceberg точно знает, какие файлы составляли таблицу в каждый момент времени.

Запросы к прошлым версиям

Прочитать данные «как они были» можно двумя способами — по ID снапшота или по времени:

-- по ID снапшота
SELECT * FROM events VERSION AS OF 1234567;

-- по времени
SELECT * FROM events TIMESTAMP AS OF '2026-04-01 12:00:00';

Так пишут в Spark SQL. В Trino синтаксис немного другой — FOR VERSION AS OF и FOR TIMESTAMP AS OF, но смысл тот же. Движок берёт ближайший снапшот на указанный момент и читает ровно тот набор файлов, что был актуален тогда.

Branches и tags

С Iceberg 1.x появились именованные ссылки на снапшоты — почти как ветки в Git, только для данных.

Branch (ветка) — изменяемая (mutable) ссылка. Используется для dev/staging-окружений и паттерна write-audit-publish: пишете и проверяете данные в отдельной ветке, а основная (main) остаётся нетронутой, пока изменения не готовы.

ALTER TABLE events CREATE BRANCH dev_branch;
-- запись именно в ветку, main не трогаем
INSERT INTO events.branch_dev_branch VALUES (...);

Tag (тег) — неизменяемая именованная ссылка на конкретный снапшот. Удобно для аудита и регуляторных срезов: зафиксировали состояние на нужную дату и храните его заданный срок.

ALTER TABLE events CREATE TAG audit_2026_05_07
  AS OF VERSION 1234567
  RETAIN 365 DAYS;

Разница простая: ветка «двигается» с новыми записями, тег навсегда указывает на один снапшот.

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Применения

  • Аудит и compliance. «Покажите записи по состоянию на 1 апреля для регулятора» — фиксируете тег на нужную дату и отдаёте воспроизводимый срез.
  • Воспроизводимость ML. Обучаете модель на конкретной версии датасета, чтобы эксперимент можно было повторить байт-в-байт даже после того, как таблицу перезаписали.
  • Отладка. Сравниваете текущее состояние с прошлым, чтобы понять, что именно изменилось после проблемной загрузки.
  • Откат (rollback). Если джоба залила битые данные, таблицу возвращают на здоровый снапшот одной командой:
CALL iceberg.system.rollback_to_snapshot('events', 1234567);

Откат тоже создаёт новый снапшот, а не удаляет историю, — то есть его самого при желании можно откатить обратно.

Частые ошибки

  • Считать time travel бэкапом. Он не защищает от удаления файлов или потери хранилища — это функция версионирования поверх тех же данных, а не резервная копия в отдельном месте.
  • Забыть про expire snapshots. Старые снапшоты живут не вечно: процедура expire_snapshots и настройки retention удаляют устаревшие снапшоты и их файлы. После этого отмотать таблицу к удалённому снапшоту уже нельзя. На собесе часто спрашивают: «Почему time travel на месяц назад вернул ошибку?» — ответ обычно в истёкшем retention.
  • Путать branch и tag. Ветка изменяемая и двигается с записями, тег неизменяемый. Записать в тег «свежие» данные не получится.
  • Ожидать time travel в любом движке. Синтаксис зависит от движка (Spark, Trino, Flink), а часть систем поверх Iceberg поддерживает чтение снапшотов ограниченно.

Связанные темы

FAQ

Чем time travel отличается от бэкапа?

Time travel — это версионирование поверх текущих данных таблицы: старые снапшоты ссылаются на те же самые data-файлы в хранилище. Бэкап — независимая копия в отдельном месте, которая переживёт удаление или сбой основного хранилища. Time travel не заменяет бэкап: если файлы физически удалены (например, процедурой expire), отмотать таблицу к ним уже нельзя.

Как долго доступны старые снапшоты?

Пока они не истекли по retention. Процедура expire_snapshots и настройки вроде максимального возраста снапшота удаляют старые снапшоты и неиспользуемые файлы, освобождая место. Если нужен долгоживущий срез (например, для аудита) — вешают на него тег с явным сроком хранения через RETAIN N DAYS.

В чём разница между branch и tag?

Branch — изменяемая ветка, которая двигается вперёд с каждой новой записью; используется для dev/staging и паттерна write-audit-publish. Tag — неизменяемая метка на конкретном снапшоте; используется для аудита и фиксации состояния на дату. Ветка — «живой» указатель, тег — «замороженный».

Как откатить таблицу на прошлое состояние?

Процедурой rollback_to_snapshot (или set_current_snapshot) — указываете таблицу и ID здорового снапшота. Откат не стирает историю, а создаёт новый снапшот, указывающий на прошлое состояние, поэтому операция обратима. Найти нужный ID можно в служебной таблице snapshots.

Это официальная информация?

Нет. Статья основана на документации Apache Iceberg. Конкретный синтаксис и поведение зависят от движка (Spark, Trino, Flink) и версии Iceberg — сверяйтесь с документацией вашего окружения.


Тренируйте Data Engineering — откройте тренажёр с 1500+ вопросами для собесов.