Learning Platform
Глоссарий Troubleshooting
Урок 12.01 · 14 мин
Продвинутый
LakehouseDelta LakeApache IcebergApache HudiOpen Table FormatData WarehouseData LakeDataFusion

Lakehouse-архитектура: от хранилищ к открытым форматам таблиц

В предыдущих модулях мы работали с DataFusion как движком для Parquet-файлов, CSV и JSON. Но в реальных аналитических системах данные живут не в россыпи файлов — они организованы в таблицы с транзакциями, версионированием и метаданными. Этот урок объясняет, почему индустрия пришла к lakehouse-архитектуре и какую роль в ней играет DataFusion.

Три поколения аналитических хранилищ

Чтобы понять lakehouse, нужно увидеть проблемы, которые решало каждое предыдущее поколение.

Эволюция аналитических хранилищ
Data WarehouseSnowflake, BigQuery, Redshift — структурированные данные, SQL, ACID, но vendor lock-in и высокая стоимость
Плюсы
Минусы
Data LakeHDFS, S3 + Hive — дёшево, любые форматы, но нет транзакций и согласованности
Плюсы
Минусы
LakehouseS3 + Delta/Iceberg + DataFusion/Spark — открытые форматы с транзакциями и метаданными
Плюсы
Роль DataFusion

Data Warehouse: структура и контроль

Классические хранилища (Snowflake, BigQuery, Redshift) предоставляют полный контроль: ACID-транзакции, оптимизированное хранение, SQL-интерфейс. Проблема в том, что данные заперты внутри проприетарного формата. Вы не можете прочитать данные Snowflake напрямую из DataFusion или Spark — только через API самого Snowflake.

Стоимость: $$$$ (compute + storage + egress)
Форматы: проприетарные
Движок: встроенный, не заменяем
Lock-in: высокий

Data Lake: свобода и хаос

Data Lake (HDFS, S3 + Hive) решил проблему стоимости и открытости: данные хранятся в Parquet/ORC на дешёвом object store, а compute отделён от storage. Но без транзакций и schema enforcement озёра превращались в “болота данных”:

  • Concurrent writers перезаписывают файлы друг друга
  • Нет атомарных обновлений — читатель видит частично записанные данные
  • Schema drift — новые поля появляются без контроля
  • Нет time travel — нельзя запросить данные “как было вчера”
Стоимость: $ (только object store + отдельный compute)
Форматы: открытые (Parquet, ORC, Avro)
Движок: любой (Spark, Presto, DataFusion)
Согласованность: отсутствует

Lakehouse: лучшее из двух миров

Lakehouse добавляет транзакционный слой поверх object store. Данные по-прежнему хранятся в открытых колоночных форматах (Parquet), но рядом лежит журнал транзакций (transaction log), который обеспечивает:

  • ACID-транзакции — атомарные записи и обновления
  • Time travel — запросы к любой версии данных
  • Schema enforcement — контроль типов при записи
  • Schema evolution — безопасное добавление и переименование колонок
  • File-level metadata — статистики min/max для пропуска файлов при чтении
TIP

Ключевая идея lakehouse: данные остаются в открытом формате (Parquet) на дешёвом storage, а транзакционная семантика обеспечивается метаданными — без vendor lock-in.

Три открытых формата таблиц

Индустрия выработала три основных формата, каждый из которых добавляет транзакционный слой поверх Parquet-файлов.

Сравнение открытых форматов таблиц
Delta LakeDatabricks, 2019. JSON transaction log, простота, широкое adoption
Transaction log
Особенности
DataFusion
Apache IcebergNetflix/Apple, 2017. Manifest-файлы, partition evolution, hidden partitioning
Transaction log
Особенности
DataFusion
Apache HudiUber, 2016. Upsert-ориентирован, record-level indexing
Transaction log
Особенности
DataFusion

Delta Lake

Создан Databricks в 2019 году. Transaction log — серия JSON-файлов в директории _delta_log/, каждый описывает набор добавленных и удалённых файлов. Периодически лог компактируется в checkpoint (Parquet-файл со снапшотом состояния).

Ключевые возможности:

  • ACID через optimistic concurrency — writer читает текущую версию, формирует commit, атомарно записывает. При конфликте — retry
  • Time travelVERSION AS OF N или TIMESTAMP AS OF '2024-01-15'
  • File-level statistics — min/max для каждой колонки в каждом файле, записанные в commit JSON. Позволяют пропускать файлы при фильтрации без чтения Parquet-метаданных
  • Change Data Feed — отслеживание изменений между версиями
storage/
├── _delta_log/
│   ├── 00000000000000000000.json   ← первый commit
│   ├── 00000000000000000001.json   ← второй commit
│   ├── 00000000000000000010.checkpoint.parquet  ← checkpoint
│   └── _last_checkpoint              ← указатель на последний checkpoint
├── part-00000-...-.parquet          ← данные
├── part-00001-...-.parquet
└── part-00002-...-.parquet

Apache Iceberg

Создан Netflix в 2017 году, развивается Apache Foundation. Использует трёхуровневую иерархию метаданных: metadata file → manifest list → manifest files → data files. Это сложнее Delta, но даёт уникальные возможности:

  • Hidden partitioning — пользователь не указывает партиционирование в запросах, движок определяет его из метаданных. SELECT * FROM events WHERE ts > '2024-01-01' автоматически использует партиционирование по month(ts)
  • Partition evolution — можно изменить схему партиционирования без перезаписи данных. Старые файлы читаются по старой схеме, новые — по новой
  • Schema evolution — безопасное добавление, удаление и переименование колонок с отслеживанием по column ID
warehouse/
├── metadata/
│   ├── v1.metadata.json              ← текущее состояние таблицы
│   ├── snap-001-manifest-list.avro   ← список manifest-файлов
│   └── manifest-001.avro             ← файлы данных + статистики
├── data/
│   ├── ts_month=2024-01/
│   │   ├── 00000-0-...-.parquet
│   │   └── 00001-0-...-.parquet
│   └── ts_month=2024-02/
│       └── 00000-0-...-.parquet
└── version-hint.text

Apache Hudi

Создан Uber в 2016 году для обработки огромных потоков данных с обновлениями. Ориентирован на upsert-сценарии: каждая запись имеет уникальный ключ, и Hudi поддерживает эффективное обновление отдельных записей без перезаписи всей партиции.

NOTE

В экосистеме DataFusion полноценная интеграция реализована для Delta Lake и Iceberg. Hudi-таблицы можно читать как Parquet-файлы (без транзакционной семантики), но нативной интеграции с поддержкой timeline и compaction нет.

Роль DataFusion в lakehouse-архитектуре

DataFusion в lakehouse выступает как query engine layer — компонент, отвечающий за исполнение SQL-запросов поверх таблиц в открытых форматах. Это разделение ответственности:

DataFusion как query engine layer в lakehouse
SQL / DataFrame APISQL-запросы от пользователей, BI-инструментов, приложений
Query Engine (DataFusion)
Table Format
Object Store

Как DataFusion взаимодействует с форматами таблиц

Интеграция работает через trait TableProvider. Библиотеки delta-rs и iceberg-rust реализуют этот trait, предоставляя DataFusion:

  1. Schema — описание колонок таблицы
  2. File pruning — список файлов, которые нужно прочитать для конкретного запроса (на основе predicate pushdown в метаданные формата)
  3. Statistics — статистики min/max/null_count для оптимизатора

DataFusion не знает деталей transaction log — он работает с TableProvider как с абстракцией. Это позволяет подключать новые форматы без изменения самого движка.

// Rust: подключение Delta-таблицы
let delta_table = deltalake::open_table("s3://bucket/table").await?;
ctx.register_table("orders", Arc::new(delta_table))?;

// DataFusion не знает, что это Delta — видит TableProvider
let df = ctx.sql("SELECT * FROM orders WHERE date = '2024-01-15'").await?;

File pruning: ключевое преимущество

Без открытого формата таблиц DataFusion читает все Parquet-файлы и фильтрует внутри каждого. С Delta Lake или Iceberg движок получает предварительно отфильтрованный список файлов:

File pruning с Delta Lake
WHERE date = ‘2024-01-15’SQL-запрос с WHERE-условием
Без формата таблицБез Delta: читаем все файлы
Чтение
I/O
С Delta LakeС Delta: transaction log содержит min/max по date
Чтение
I/O

Для таблицы с 1000 файлов это разница между чтением 1000 Parquet-footer и чтением одного JSON-файла с метаданными. На практике это даёт ускорение в 2-10x для селективных запросов.

Выбор формата: Delta Lake vs Iceberg

На март 2026 года оба формата активно развиваются и поддерживаются в экосистеме DataFusion:

КритерийDelta LakeApache Iceberg
Зрелость в DataFusiondelta-rs — стабильная интеграция с DF ≥43.0.0iceberg-rust — активная разработка, DF ≥45.0.0
Transaction logJSON-файлы (простой формат, легко дебажить)Avro manifest-файлы (сложнее, но эффективнее при большом количестве файлов)
Partition evolutionНет — партиционирование фиксировано при созданииДа — можно изменить схему партиционирования без перезаписи
Hidden partitioningНет — пользователь явно указывает partition columnsДа — движок выводит партиционирование из метаданных
Schema evolutionAdd/rename columnsAdd/rename/drop columns с column ID tracking
ЭкосистемаSpark, DataFusion, Polars, DuckDBSpark, Flink, Trino, DataFusion
Python APIdeltalake (delta-rs bindings)pyiceberg (iceberg-rust bindings)
TIP

Правило выбора: если уже используете Databricks/Spark-стек — Delta Lake. Если нужна максимальная гибкость метаданных и multi-engine support — Iceberg. Для DataFusion оба формата интегрируются одинаково — через TableProvider.

Архитектурные паттерны lakehouse с DataFusion

Паттерн 1: Embedded analytics

DataFusion встраивается в приложение как библиотека (in-process). Данные читаются из Delta Lake на локальном диске или S3:

// Rust: embedded analytics engine
let ctx = SessionContext::new();
let delta = deltalake::open_table("./data/events").await?;
ctx.register_table("events", Arc::new(delta))?;

// SQL-запросы исполняются in-process, без сетевых вызовов
let result = ctx.sql("
    SELECT user_id, count(*) as event_count
    FROM events
    WHERE event_date >= '2024-01-01'
    GROUP BY user_id
    ORDER BY event_count DESC
    LIMIT 100
").await?;

Паттерн 2: Query service

DataFusion работает как сервер (например, через Arrow Flight SQL), обслуживая множество клиентов. Таблицы Delta/Iceberg регистрируются при старте:

Клиенты (BI, notebooks, приложения)


  ┌─────────────┐
  │ Flight SQL   │  ← DataFusion + Arrow Flight
  │ Server       │
  └──────┬──────┘

    ┌────┴────┐
    │         │
Delta Lake  Iceberg    ← TableProvider
    │         │
    S3 / GCS / Azure   ← Object Store

Паттерн 3: ETL pipeline

DataFusion читает данные из одного формата, трансформирует и записывает в другой. Типичный сценарий — миграция с raw Parquet на Delta Lake:

# Python: миграция Parquet → Delta Lake
import datafusion
from deltalake import write_deltalake

ctx = datafusion.SessionContext()
ctx.register_parquet("raw_events", "s3://raw-bucket/events/")

# Трансформация через SQL
result = ctx.sql("""
    SELECT
        event_id,
        user_id,
        event_type,
        CAST(timestamp AS TIMESTAMP) as event_ts,
        DATE_TRUNC('day', CAST(timestamp AS TIMESTAMP)) as event_date
    FROM raw_events
    WHERE event_type IS NOT NULL
""")

# Запись в Delta формат
write_deltalake(
    "s3://lakehouse/events",
    result.to_arrow_table(),
    partition_by=["event_date"],
    mode="overwrite"
)

Что дальше

В следующих уроках мы подробно разберём каждый формат:

  • Урок 02 — Delta Lake: интеграция с DataFusion, time travel, file-level metadata skipping
  • Урок 03 — Apache Iceberg: каталоги, hidden partitioning, partition evolution
  • Урок 04 — Object Store: доступ к S3/GCS/Azure, конфигурация credentials, выбор между форматами
NOTE

Все примеры кода в этом модуле используют DataFusion v53.0.0+ (Python v53.0.0, релиз 2026-04-02). API для более ранних версий может отличаться — проверяйте совместимость в changelog проекта.

Ключевые выводы

  1. Lakehouse = открытые колоночные форматы (Parquet) + транзакционный слой (Delta/Iceberg) + дешёвый object store
  2. DataFusion выступает как query engine layer — не знает деталей формата, работает через TableProvider
  3. Delta Lake — простой transaction log (JSON), хорошая интеграция с DataFusion через delta-rs
  4. Apache Iceberg — сложнее, но гибче (hidden partitioning, partition evolution), интегрируется через iceberg-rust
  5. File pruning — главное преимущество формата таблиц: движок читает только нужные файлы, пропуская остальные по метаданным
Real-time analytics в data-platform

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. Какую проблему Data Lake решает lakehouse-архитектура?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4