Documentation
🏛️ Data Warehouse / Data Lake / LakeHouse
Iceberg

Apache Iceberg

Что это такое

Apache Iceberg — это открытый табличный формат для озёр данных. Он даёт Data Lake свойства полноценного хранилища:

  • транзакции (ACID),
  • историю изменений (snapshots / time travel),
  • эволюцию схемы без переливки данных,
  • быстрый SQL-доступ.

Зачем он нужен

DWH хорошо работают со структурированными данными, но дорогие и жёсткие. Data Lake дешёвые и гибкие, но без транзакций и контроля качества.

Iceberg — это компромисс:

  • хранение в озере,
  • работа как с таблицами в DWH.

Ключевые преимущества

  • ACID-транзакции без централизованной БД
  • Time Travel — чтение таблицы в прошлом
  • Эволюция схемы и партиций без перезагрузки данных
  • Совместимость со Spark, Flink, Trino, Dremio и др.
  • Масштабируемость до петабайтных объёмов

Архитектура Iceberg (очень кратко)

apache iceberg

1) Data Layer

Файлы данных (Parquet/ORC/Avro) + delete files.

2) Metadata Layer

Манифесты, снапшоты, схема, партиции, статистика.

3) Catalog Layer

Точка входа для движков (Hive Metastore, Glue, Nessie, JDBC/REST).


Файлы удаления и стратегии записи

Iceberg поддерживает два подхода:

Copy-on-Write (COW)

  • переписывает файлы при изменении;
  • проще читать, дороже писать.

Merge-on-Read (MOR)

  • фиксирует изменения в delete files;
  • быстро пишет, чуть тяжелее читать.

Примеры работы с Iceberg

Ниже примеры разбиты по отдельным операциям.

1) Запуск Spark-сессии с Iceberg

from pyspark.sql import SparkSession
 
spark = (
    SparkSession.builder
    .appName("IcebergExample")
    .config("spark.sql.catalog.my_catalog", "org.apache.iceberg.spark.SparkCatalog")
    .config("spark.sql.catalog.my_catalog.type", "hive")
    .config("spark.sql.catalog.my_catalog.uri", "thrift://localhost:9083")
    .getOrCreate()
)

2) Создание таблицы

CREATE TABLE my_catalog.db.orders (
  order_id BIGINT,
  customer_id BIGINT,
  amount DECIMAL(10,2),
  created_at TIMESTAMP
)
USING iceberg
PARTITIONED BY (days(created_at))

3) Time Travel по snapshot-id

SELECT * FROM my_catalog.db.orders VERSION AS OF 918273645

4) Time Travel по времени

SELECT * FROM my_catalog.db.orders TIMESTAMP AS OF '2025-09-28 14:00:00'

5) Компактизация файлов

CALL my_catalog.system.rewrite_data_files('db.orders')

6) Очистка старых снапшотов

CALL my_catalog.system.expire_snapshots('db.orders')
  WHERE committed_at < TIMESTAMP '2025-09-01 00:00:00'

7) Удаление orphan-файлов

CALL my_catalog.system.remove_orphan_files('db.orders')

Пример MERGE и DELETE

MERGE (обновление и вставка)

MERGE INTO my_catalog.db.orders t
USING my_catalog.db.orders_updates s
ON t.order_id = s.order_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *

DELETE (удаление по условию)

DELETE FROM my_catalog.db.orders
WHERE amount = 0

Iceberg vs Delta vs Hudi (в двух словах)

Все три — open table formats для Lakehouse. Отличия чаще всего в экосистеме и деталях.

ФорматСильная сторонаГде часто используют
IcebergПортируемость, нейтральность к движкамSpark, Trino, Flink
DeltaГлубокая интеграция с DatabricksDatabricks, Spark
HudiХорош в стриминге и CDC-сценарияхSpark, Flink

На практике выбор часто зависит от стека и команды, а не только от формата.