Big Data

Delta Lake, Iceberg, Hudi

Data Lake на S3 - это просто папка с Parquet-файлами. Никаких транзакций, никакой истории, никакого контроля схемы. В 2016-2019 годах Netflix, Uber и Databricks независимо пришли к одному выводу: нужен слой метаданных поверх файлов, который даст ACID-гарантии без переезда в классическую БД. Так появились Iceberg, Hudi и Delta Lake - три формата, которые теперь стали стандартом индустрии.

  • **Netflix** использует Iceberg для 10+ петабайт данных - schema evolution позволяет изменять схемы без остановки пайплайнов
  • **Uber** создал Hudi для real-time аналитики поездок - upsert-ы по trip_id с задержкой <5 минут от события до видимости в Presto
  • **Databricks** включил Delta Lake в Apache Spark и Lakehouse Platform - OPTIMIZE + Z-Order снижают время аналитических запросов в 10-100x

ACID поверх Data Lake

2019 год: аналитик Uber запускает UPDATE на таблице с поездками - и получает несогласованные данные, потому что другой Job читал её в тот же момент. Data Lake на S3 не знает ни о каких транзакциях: файлы просто лежат, и никто не координирует доступ. **Delta Lake, Apache Iceberg и Apache Hudi** - это форматные слои поверх Parquet, которые добавляют ACID без замены хранилища.

Ключевая идея: вместо того чтобы редактировать файлы на месте (что невозможно в S3), система ведёт **transaction log** - журнал всех операций. Каждая запись в log-е атомарна. Читатель смотрит в log, определяет какой набор файлов актуален, и читает только их.

ФорматРазработчикЛог транзакцийОсобенность
Delta LakeDatabricks_delta_log/*.jsonЛучшая интеграция со Spark/Databricks
Apache IcebergNetflix/Applemetadata/*.avroЛучший для multi-engine (Flink, Trino, Spark)
Apache HudiUber.hoodie/Оптимизирован для частых upsert-ов

**Оптимистичный concurrency:** Delta Lake использует optimistic locking - два writer-а пишут параллельно, но при commit проверяется конфликт. Если оба меняли одни файлы - один получает ConflictException и должен повторить. Это лучше, чем пессимистичные блокировки, которые блокируют читателей.

Delta Lake обеспечивает ACID на S3 с помощью:

Time Travel

Аналитик случайно удалил 500 тысяч строк из production-таблицы. В обычном Data Lake данные потеряны. В Delta Lake через 10 минут таблица восстановлена командой из одной строки - потому что каждый commit сохранён в лог, а старые файлы не удаляются сразу.

**Time travel** работает потому, что операции DELETE и UPDATE в Delta Lake не редактируют Parquet-файлы. Они добавляют запись в лог (`remove` для старых файлов, `add` для новых). Старые файлы остаются на диске до явного `VACUUM`. Запрос с указанием версии или timestamp просто читает состояние лога на тот момент времени.

**Iceberg** хранит не лог-файлы, а snapshot-дерево: каждый commit создаёт новый snapshot-метафайл, который ссылается на manifest-list, который ссылается на manifest-файлы с путями к Parquet. Time travel = выбор нужного snapshot-а. Механизм другой, результат тот же.

После случайного `DELETE FROM sales WHERE region='EU'` данные можно восстановить потому что:

Schema Evolution

Команда решила добавить колонку `discount_percent` в таблицу заказов. Проблема: старые Parquet-файлы этой колонки не содержат. Обычный Data Lake сломается или вернёт null для старых строк без контроля. **Schema Evolution** в Delta Lake/Iceberg/Hudi решает это контролируемо: схема таблицы эволюционирует, а совместимость гарантируется.

Есть два режима: **schema merging** (автоматически добавляет новые колонки) и **schema enforcement** (отклоняет данные с неожиданной схемой). По умолчанию Delta Lake включает enforcement, что защищает от случайной порчи данных. Evolution нужно явно разрешить.

**Iceberg Column IDs:** Iceberg хранит в метаданных не имена колонок, а их числовые id. Parquet-файл написан с id=3 для колонки `price`. После переименования в `amount` - id остаётся 3. Старые файлы читаются корректно без переписи. Delta Lake до version 2.x требовал column mapping mode для такого поведения.

Iceberg лучше Delta Lake справляется с переименованием колонок потому что:

Compaction и оптимизация файлов

После месяца работы таблица с событиями выросла до 50 тысяч мелких Parquet-файлов по 1 МБ каждый. Запрос, который раньше шёл 2 секунды, теперь занимает 4 минуты: Spark тратит больше времени на открытие файлов, чем на чтение данных. Это называется **small files problem** - классическая болезнь Data Lake при потоковой записи.

**Compaction** - процесс объединения мелких файлов в крупные (оптимально 128-512 МБ для Parquet). Delta Lake называет это `OPTIMIZE`, Iceberg - `rewrite_data_files`, Hudi - `compaction`. Дополнительно можно применить **Z-Order** - многомерную сортировку, которая физически совмещает связанные данные в одних файлах.

**VACUUM** vs **OPTIMIZE** - разные операции: OPTIMIZE объединяет мелкие файлы в крупные (улучшает скорость чтения). VACUUM удаляет старые файлы, помеченные как removed в delta_log (освобождает место). VACUUM ломает time travel за пределами retention period. Рекомендуемая последовательность: OPTIMIZE ежедневно, VACUUM еженедельно с RETAIN 168 HOURS.

VACUUM удаляет ненужные дубликаты и ускоряет запросы

VACUUM только освобождает дисковое место, удаляя файлы помеченные в delta_log как removed. На скорость чтения он не влияет. Для скорости нужен OPTIMIZE.

Смешение двух операций с похожими названиями - частая ошибка. OPTIMIZE = быстрее читать. VACUUM = меньше хранить.

Z-Order ускоряет запросы за счёт:

Delta Lake, Iceberg, Hudi

  • ACID поверх S3/HDFS через transaction log: каждый commit атомарен, читатели видят согласованный snapshot
  • Time travel: DELETE/UPDATE не удаляют файлы физически - старые данные доступны до явного VACUUM
  • Schema evolution: добавление колонок без переписи файлов; Iceberg лидирует в rename через column_id
  • Small files problem решается через OPTIMIZE/compaction + Z-Order для data skipping
  • Выбор формата: Delta Lake для Spark/Databricks, Iceberg для multi-engine, Hudi для частых upsert-ов

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

Table formats надстраиваются над базовыми компонентами Big Data стека:

  • Parquet и колоночное хранение — Физический формат файлов под Delta/Iceberg/Hudi
  • Spark: трансформации и действия — Основной движок для OPTIMIZE, VACUUM и аналитики
  • Data Warehouse vs Data Lake — Lakehouse Architecture объединяет оба подхода

Вопросы для размышления

  • В каких сценариях time travel с retention 7 дней недостаточен - и как это решить без увеличения retention?
  • Почему Z-Order по двум колонкам хуже, чем по одной - и как пространственные кривые Гильберта смягчают эту проблему?
  • Компания переходит с Hive таблиц на Delta Lake. Какие риски несёт изменение meta.id существующих таблиц для downstream пайплайнов?

Связанные уроки

  • db-03-acid
Delta Lake, Iceberg, Hudi

0

1

Войти