Learning Platform
Глоссарий Troubleshooting
Урок 15.01 · 25 мин
Продвинутый
Streaming lakehousePaimonIcebergHudiOpen table formatsStreaming ingestion

Streaming lakehouse: Paimon vs Iceberg vs Hudi

В 2020-2022 годах появилось три open table format-а — Apache Iceberg, Apache Hudi и Delta Lake (open source часть). Все три обещали “lakehouse” — комбинацию batch data lake (S3 + Parquet) с warehouse-properties (ACID, schema evolution, time travel). Это поколение сделало batch-аналитику на data lake-ах серьёзным конкурентом proprietary warehouse-ам (Snowflake, BigQuery).

Apache Iceberg: глубокое погружение (Spark perspective) Apache Paimon: глубокое погружение (Spark perspective) Lakehouse коннекторы в Flink: Paimon, Iceberg, Hudi

Но было одно слабое место — streaming. Iceberg хорош для batch, но streaming в нём — это compromised: micro-batch commits, мелкие файлы, проблемы с low-latency reads. Hudi был спроектирован с CDC use case, но и его streaming-возможности имели ограничения.

Apache Paimon (graduate Apache в 2024) появился как streaming-first lakehouse: с самого начала спроектирован для high-throughput continuous ingestion из Flink с low-latency consume того же data. Этот урок: какое место занимает Paimon, чем он отличается от Iceberg/Hudi, и когда что выбирать.


Что такое lakehouse

Сначала контекст. Три поколения analytical data systems:

Data warehouse (1980s-2010s). Teradata, Oracle, потом Snowflake, BigQuery, Redshift. Proprietary format, hardware-software bundled. ACID, schema evolution, fast queries. Не открыт — вендор-lock, проdата expensive.

Data lake (2010s). Files on HDFS/S3. Open formats: CSV, JSON, потом Parquet, ORC. Дёшево, scalable, но без ACID, без schema enforcement. Hive Metastore как weak abstraction. Queries через Spark, Presto, Trino.

Lakehouse (2020s). Open table formats на S3/cloud-storage: Iceberg, Hudi, Delta. ACID transactions, schema evolution, time travel — всё что warehouse имеет, но на open files. Multiple engines читают (Spark, Trino, Flink, Snowflake-external).

Lakehouse не новое хранилище, а новая абстракция над files. Под капотом — Parquet/ORC файлы + manifest файлы + metadata. Engine читает manifest (small) -> знает какие data files (large) ему нужны -> читает только их. Mutations работают через snapshot-isolation: новые versions создают новые files, манифест обновляется atomically.


Что такое streaming lakehouse

Classic lakehouse решает batch workloads. Streaming — это другая категория проблем:

  • Continuous ingestion: не один insert каждые часы, а тысячи rows/sec из Flink/Kafka.
  • Low-latency reads: query видит новые данные через секунды, не часы.
  • Mutations as first-class: streaming CDC из source DB (upserts, deletes), а не append-only.
  • Hybrid queries: один и тот же таблица — и для real-time dashboard, и для batch ML training.

Iceberg с такими workload-ами справляется плохо. Каждый Flink checkpoint = 1 commit = 1 snapshot. С checkpoint interval 1 минуту получаем 1440 snapshots/day. Manifest growth -> query planning slow. Мелкие data files (Flink subtask за minute не успевает записать большой parquet) -> query reads много мелких files, slow. Solution — async compaction process, но он сам конкурирует с writer-ами.

Paimon спроектирован специально для streaming:

  • LSM-tree storage: маленькие L0 files compacted-ятся в большие L1/L2. Сразу аналогия с RocksDB.
  • Snapshot per checkpoint: но snapshots cheap, и automatic compaction поверх.
  • Streaming reads: consumer может subscribe на таблицу, получать changes по мере commit-ов (как Kafka topic).
  • Built-in changelog: операция UPDATE на primary-key table генерирует -U, +U records — это можно consume downstream-у через streaming read.

Сравнение: Paimon, Iceberg, Hudi

Сравнение open table formats
Storage organizationКак организованы data files внутри таблицы — фундаментальный design decision
Icebergflat snapshotsКаждый snapshot — set of data files + delete files. Манифест tree. Нет уровней — все files на одном уровне
HudiMOR / COWCopy-on-write: каждый update создаёт новый file. Merge-on-read: base file + delta log files, merge at read time
PaimonLSM-treeL0 (recent small) -> L1 -> L2 (большие, compacted). Аналогично RocksDB. Compaction в background
Optimal use caseГде данный формат показывает лучшее
Icebergbatch ETL, large readsSnowflake-like queries. Append-only или large UPDATEs. Multi-engine ecosystem (Spark, Trino, Flink)
HudiCDC ingestionInitial use case — Uber для DB CDC в data lake. Primary-key tables, frequent upserts
Paimonstreaming both waysContinuous Flink ingestion, low-latency streaming reads. CDC + analytics в одной таблице. Built for Flink-Paimon symbiosis
Ingestion latencyВремя от arrival события до visibility в queries
IcebergminutesКаждый commit = snapshot. Слишком частые commits — manifest growth. Practical минимум 1-5 минут
HudiminutesSimilar to Iceberg. Slightly faster with MOR (delta log appends fast)
PaimonsecondsLSM L0 ingestion fast. Snapshot per checkpoint OK, потому что compaction handles file growth
Read latencyВремя от query начала до result
Icebergseconds-minutesManifest scan + parallel parquet read. Большие queries — оптимизирован
Hudiseconds-minutesMOR slower (merge at read). COW faster reads (но slower writes)
PaimonsecondsLSM read = scan L0+L1+L2 in parallel + merge. Optimized для primary-key lookups через Bloom filters

Streaming-first vs batch-first

Дизайн различия видны на простом сценарии:

Сценарий: Flink job, который consumes Kafka topic с CDC из MySQL. 50 tables, average 500 events/sec на table, peak 5000. Sink в lakehouse. Downstream — два consumer-а: BI dashboard (Trino queries каждые 30 sec) и feature store (streaming read continuous).

С Iceberg:

  • Flink checkpoint interval 1 минуту -> 60 commits/час -> 1440 commits/день на 50 таблиц = 72000 snapshots.
  • Каждый commit = small parquet file (500 records * 60 sec = 30000 rows ≈ 100KB Parquet — слишком мало).
  • Через сутки в таблице 1440 файлов по 100KB = 144MB. Query plan = чтение 1440 файлов parallel — каждый open() = S3 latency, total 5-10 секунд только на open-ы.
  • Решение: scheduled compaction Spark/Flink job, каждый час merge мелкие в большие. Но это external pipeline, его нужно maintain.
  • Streaming read для feature store — Iceberg поддерживает (SELECT ... FROM table /*+ OPTIONS('streaming'='true') */), но reading new snapshots каждые seconds — overhead и low-latency проблематичен.

С Paimon:

  • Тот же checkpoint = snapshot, но Paimon делает в background compaction L0 -> L1 -> L2.
  • Через сутки таблица имеет ~10 больших файлов в L2 (compacted) + новые L0 files. Reader читает L2 + applying changes from L0 (in-memory).
  • Streaming read native — connector подписывается на snapshots, читает changes incrementally. Это эффективнее чем повторные SELECT.
  • Trino через Paimon connector читает latest snapshot (или specific snapshot для time-travel). Снова — L2 files давно compacted, query быстрая.

Paimon разрабатывался изначально с этим в виду. Iceberg — fits batch workloads, streaming retrofitted позже.


Когда что выбирать

Choice matrix:

Use caseBest fitReason
Append-only batch ETL (web logs, IoT)IcebergMulti-engine (Spark/Trino), mature ecosystem
Open data sharing (vendor-neutral)IcebergWide engine support, AWS Glue catalog standard
Snowflake/BigQuery external tablesIcebergNative external table support
CDC ingestion from RDBMSPaimonBuilt-in PK support, streaming reads, changelog
Real-time analytics (sub-min latency reads)PaimonLSM-tree designed for this
Flink streaming primaryPaimonFlink-Paimon team works together, deepest integration
Mixed batch + streaming на одной таблицеPaimonUnified, single source of truth
Hudi-legacy migrationHudiStay if invested
Iceberg-legacy migrationIcebergStay if invested, или migrate to Paimon если streaming pain

Не “одно лучше всех” — это разные tools для разных проблем. Большие компании используют оба: Iceberg для batch warehouse-данных, Paimon для streaming/CDC.


Flink — главный engine, который читает/пишет во все три формата:

// Iceberg
FlinkSink.forRowData(stream)
    .table(table)
    .tableLoader(tableLoader)
    .writeParallelism(8)
    .append();

// Paimon
PaimonSink.<RowData>builder()
    .withCatalog(catalog)
    .withTable("orders")
    .build();

// Hudi
HoodiePipeline.Builder builder = HoodiePipeline.builder("h_orders")
    .column("id BIGINT")
    .column("name STRING")
    .pk("id")
    .options(...);

Под капотом все три используют FLIP-143 Sink V2 protocol (Writer + Committer + GlobalCommitter). GlobalCommitter создаёт snapshot/commit atomically. Это даёт exactly-once.

SQL access одинаков:

-- Catalog setup
CREATE CATALOG paimon_cat WITH (
  'type' = 'paimon',
  'warehouse' = 's3://bucket/paimon/'
);

USE CATALOG paimon_cat;

-- Streaming write
INSERT INTO orders SELECT * FROM kafka_orders;

-- Batch read
SELECT * FROM orders WHERE date = '2026-05-19';

-- Streaming read
SELECT * FROM orders /*+ OPTIONS('streaming'='true') */;

-- Time travel
SELECT * FROM orders /*+ OPTIONS('scan.snapshot-id'='12345') */;

Это новая концепция в Flink, которая поверх Paimon (или другого lakehouse) даёт еще один уровень абстракции:

CREATE MATERIALIZED TABLE order_summary
  REFRESH MODE = CONTINUOUS    -- streaming или batch refresh
  FRESHNESS = INTERVAL '5' MINUTE  -- максимальное отставание от source
AS
SELECT date, count(*), sum(amount)
FROM orders
GROUP BY date;

Flink сам решает: запустить continuous streaming job (FRESHNESS = seconds) или scheduled batch job (FRESHNESS = hours). Storage — Paimon (или другой supported lakehouse). Это unified API для batch и streaming aggregations. Подробнее в уроке 04-materialized-tables.


Apache Fluss (incubating)

Кроме lakehouse, в экосистеме Flink появляется Fluss — это streaming-first storage (не table format, а complete storage layer). Альтернатива Kafka, оптимизирована для analytics:

  • Column-oriented (vs Kafka row-oriented) — query даёт server-side projection.
  • Sub-second consume latency (как Kafka), но при этом columnar — фильтры на server side.
  • Integrated с Paimon — Fluss может materialize в Paimon table.

Fluss vs Kafka: Kafka — universal log storage, Fluss — narrow analytical streaming. Подробнее в уроке 05-fluss-streaming-storage.

NOTE

Иногда возникает confusion: “Paimon” и “Fluss” — это связанные но разные вещи. Paimon — lakehouse storage (как Iceberg). Fluss — streaming storage (как Kafka). Они дополняют друг друга: Fluss как hot streaming layer, Paimon как cold lakehouse layer. Flink job может писать в Fluss для real-time, и параллельно/eventually materialize в Paimon для batch analytics.


Production-перспектива: миграция и interop

Многие компании сейчас в процессе migration с Iceberg/Hudi на Paimon (или наоборот). Practical advice:

Не мигрируй без причины. Если Iceberg работает и нет pain — оставь. Migration cost (data copy, pipeline rewrite, testing) большой.

Мигрируй если streaming pain. Если у тебя Iceberg с 1000+ snapshots/час и постоянные compaction job-ы fighting writers — Paimon уберёт боль.

Try interop. Paimon может read Iceberg (через Paimon Iceberg compatibility). Можно делать gradual migration: новые tables на Paimon, старые на Iceberg, постепенно сливать.

Catalog wars. Iceberg ecosystem стандартизировался на AWS Glue / Nessie / Polaris. Paimon ещё имеет свой catalog (file-based or Hive). Если у тебя Glue / Snowflake-external setup -> Iceberg natural fit.


Проверка знанийKnowledge check
Команда строит real-time analytics pipeline: Flink consumes Kafka CDC (50 MySQL tables, 1000-5000 events/sec each), sinks в lakehouse. BI dashboard (Trino) запрашивает каждые 30 секунд latest data. ML feature store нужен streaming consume той же таблицы для real-time predictions. Чекпоинт интервал 30 секунд. Какой lakehouse выбрать и почему?
ОтветAnswer
Choice: Paimon. Reasoning: (1) Streaming-first design подходит: 30-second checkpoint = 30-second commit, Paimon LSM-tree organization handles это нативно. С Iceberg такая частота creates massive manifest growth (2880 commits/day на table) и тысячи мелких parquet files — query plan slow, requires constant compaction. (2) CDC use case: Paimon native поддержка primary-key tables, changelog generation (-U, +U records на updates) — это нужно для feature store streaming consume. Iceberg тоже поддерживает upserts через delete files, но не оптимизирован для high-frequency. (3) Streaming reads native в Paimon: feature store подписывается на snapshots, читает incremental changes как поток. Iceberg streaming reads existed но retrofitted, less efficient. (4) Trino через Paimon connector читает latest snapshot — за счёт background compaction L2 files большие, query быстрая. (5) Single table для batch и streaming consume — Paimon strength. Avoid дублирование (Iceberg для BI + Kafka для feature store). Risk: Paimon younger than Iceberg, ecosystem (особенно outside Flink) меньше. Если в команде уже Spark-centric с Iceberg expertise — миграция cost будет. Если greenfield + Flink primary — Paimon clear winner для этого профиля.

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

Результат: 0 из 0
Концептуальный
Вопрос 1 из 4. Главное архитектурное различие между Paimon и Iceberg, которое объясняет, почему Paimon лучше для streaming workloads?

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

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

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

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