Open table formats (Apache Iceberg, Delta Lake, Apache Hudi) — metadata layer over Parquet/ORC files on S3/GCS/ADLS that adds ACID transactions, snapshot isolation, time-travel, schema/partition evolution, efficient updates. Lakehouse architecture: cheap object storage + warehouse semantics. Catalogs: REST, Polaris, Nessie, Glue, Hive Metastore, Unity Catalog. Scenarios: atomic write commit (parquet + manifest + CAS), concurrent writers with optimistic retry, time-travel query (timestamp → snapshot id), MoR vs CoW trade-off with compaction, schema/partition evolution without rewrite, full read path with manifest pruning, maintenance (compaction, snapshot expiration, orphan cleanup). Includes ADRs on Iceberg vs Delta vs Hudi selection and CoW vs MoR write-vs-read trade-off.
Parquet на S3 — это compression и predicate pushdown, но НЕ:
ACID, snapshot isolation, schema evolution, time-travel, эффективные
UPDATE/DELETE, координация параллельных writer-ов, статистика для
query-планировщика. Без всего этого "data lake" — это свалка файлов:
два job-а одновременно пишут в dt=2026-05-14/, reader видит partial
state; добавил колонку — старые файлы её не имеют, query падает;
"покажи как было вчера" — нет такой кнопки; обновить одну строку —
переписать весь parquet.
Table formats (Apache Iceberg, Delta Lake, Hudi) добавляют metadata layer поверх Parquet/ORC на object storage. Появляются ACID-транзакции через optimistic concurrency, snapshot isolation, schema/partition evolution, time-travel, statistics, row-level updates. Получается lakehouse: object storage за $0.023/GB + warehouse-семантика.
Экономический эффект огромный. Snowflake/Redshift на 1 PB — $100K-500K/год. Lakehouse (Iceberg на S3 + Trino/Spark/Athena) — в 5-10x дешевле по storage + pay-per-query compute. Netflix, Apple, Adobe, Stripe сэкономили миллионы, переехав с warehouse на lakehouse. И выбор формата — архитектурный: от него зависит, какими engine-ами ты сможешь читать, как обрабатывать streaming upserts, какой governance.
Table format = metadata layer над Parquet/ORC на object storage, добавляющий ACID, snapshot isolation, schema/partition evolution, time-travel, row-level updates. Превращает S3 в transactional warehouse-like table.
Три ключевые идеи:
Writers (Spark batch + Flink streaming) — два разных профиля: Spark делает большие коммиты редко, Flink — частые микро-batch-и (streaming ingest).
Iceberg Catalog (REST/Polaris/Glue/Nessie) — единственный источник правды о том, какой snapshot "текущий". Здесь происходит атомарный CAS commit. Без catalog-а каждый engine считал бы себя главным — race conditions и потеря данных.
S3 с двумя группами:
metadata/ — v*.metadata.json (table-level: schema, partition
spec, current snapshot ptr), snap-*.avro (manifest list для
snapshot), manifest-*.avro (списки data files + column stats).data/ — parquet файлы с spec_id (с каким partition layout
записан этот файл) и опционально log-*.avro для Merge-on-Read
delta-логов.Readers (Trino, Snowflake, DuckDB, Athena/Spark SQL) — все ходят через catalog, читают свой snapshot, никто никого не блокирует.
Maintenance (Compactor + Snapshot expirer) — отдельные scheduled job-ы для гигиены: compact мелких файлов, expire старых snapshot-ов, удаление orphan-ов после failed commits. Без них lakehouse деградирует за дни/недели.
7 сценариев. Каждый — критический аспект работы table format-а.
write — атомарный commit. GET current metadata → PUT parquet
→ PUT manifest + snap list → PUT new metadata.json → CAS commit к
catalog. Snapshot isolation: reader до CAS видит старый snapshot,
после — новый.
concurrent — конкурентные writer-ы. Два читают одну base,
оба пишут свои файлы, один выигрывает CAS, второй получает
CommitFailedException (Iceberg) / ConcurrentAppendException
(Delta), читает новый snapshot, ребейзит (файлы уже на S3, не
переписываем!) и ретраит. Это и есть ACID over object storage.
Glue throttle при >100 ops/sec — лечится REST catalog (Polaris/Tabular)
или DynamoDB lock.
time-travel — FOR TIMESTAMP AS OF. Catalog резолвит
timestamp в snapshot_id, reader читает старые metadata + manifest
mor-vs-cow — Copy-on-Write vs Merge-on-Read. Streaming CDC
10K UPSERT/sec: CoW переписывает 50MB parquet на каждый upsert
(write amp x50000). MoR пишет ~100B delta record в log — write
throughput высокий, но read деградирует (5x через 30 min, 100x
через 24h). Лечение — compactor каждые 30 min.
schema-evo — evolution без rewrite. Killer feature Iceberg:
ADD/DROP/RENAME COLUMN, ADD PARTITION FIELD — meta-only, ZERO data
rewrites. Schema resolution по field_id, а не по имени. Старые
файлы pruning по date only, новые — по date+bucket. Один SQL —
Iceberg сам резолвит layout per file. В Hive это месяцы миграции
PB-таблицы.
read-path — почему запрос быстрый. 4 round trip-а (catalog
~10ms, metadata.json ~5ms, snap-list ~20ms, manifests parallel
~50ms), три фазы pruning (partition → column stats → bucketing) —
из 1000 файлов остаётся 1, читаем ~50ms. Итого ~135ms. Без column
stats — 50 секунд. Manifest stats == lakehouse magic.
maintenance — compact + expire + orphan cleanup. Streaming
пишет 1800 файлов по 1MB за 30 мин — query 54 сек. rewrite_data_files
→ 14 файлов по 128MB — 420ms (100x speedup). expire_snapshots
удаляет старые snapshot-ы (retention 7-30 dev, 30-90 prod).
remove_orphan_files чистит мусор от failed commits — DESTRUCTIVE,
safety window 24h, чтобы не снести in-flight uploads.
Скрипт несёт два архитектурных решения на узле catalog-svc.
Контекст. Все три решают одну задачу — ACID + snapshot isolation
Решение. Default 2026: Iceberg для нового greenfield lakehouse — широкая engine support (не лочишься на вендора), зрелая schema evolution, Polaris/Tabular ecosystem набирает массу. Delta Lake — если ты уже всецело на Databricks (95% workload в Spark, MERGE-heavy ETL, Unity Catalog). Hudi — узкая ниша: high-frequency CDC-upserts (>10K/sec). Mixed strategy в крупных компаниях — норма (Iceberg для BI, Hudi для realtime CDC, Delta где legacy Spark). Interop: Apache XTable (UniForm) — таблица читается как любой формат.
Контекст. Два режима update с экстремальными trade-off:
Решение. CoW — для 95% batch analytics (load nightly, query
целый день, UPDATE/DELETE редки). Read остаётся быстрым. MoR —
только high-frequency upsert сценарии: CDC из OLTP, IoT telemetry,
SCD-таблицы. Обязательно настроить compaction (Hudi async every
10-30 min; Iceberg scheduled rewrite_data_files). Без compaction
MoR read деградирует 10-100x за дни.
count(*)). Решение:
rewrite_data_files / OPTIMIZE каждые 1-6 часов.expire_snapshots не настроен. Storage растёт линейно с
retention — через год двойной storage от живых данных. Retention
7-30 дней dev, 30-90 prod; отдельные TAG для critical snapshots.OPTIMIZE слишком частый. Compaction перезаписывает гигабайты
→ S3 PUT cost ($$$). Балансируйте latency vs write cost.remove_orphan_files без safety window. Может снести
in-flight uploads. Retention 24h минимум.expire_snapshots сносит через 30 дней — отдельные
TAG для audit snapshots, они НЕ expire.