1. Плюсы и минусы Apache Iceberg
Плюсы и минусы Apache Iceberg
Представьте, что вы — архитектор данных в крупном ритейлере. У вас десятки терабайт транзакций, лежащих в S3 в формате Parquet, поверх которых построен Hive. Запросы аналитиков тормозят, потому что каждый SELECT с фильтром по дате вынужден сканировать тысячи мелких файлов. Партиционирование по году и месяцу помогает, но когда кто-то случайно записывает данные не в ту партицию — возникают дубли. Откатить ошибочную вставку можно только вручную, перезаписав файлы. Знакомо? Именно для решения таких проблем был создан Apache Iceberg — открытый табличный формат, который превращает «просто набор файлов» в полноценную таблицу с гарантиями целостности.
Но Iceberg — не волшебная таблетка. У него есть свои ограничения, компромиссы и области, где альтернативы оказываются лучше. Прежде чем переходить на него, нужно честно понять обе стороны.
Что Iceberg даёт «из коробки»
ACID-транзакции поверх объектного хранилища. S3 и HDFS — это файловые системы без встроенных транзакций. Iceberg решает это на уровне метаданных: каждое изменение таблицы фиксируется атомарным обновлением указателя на новый снепшот. Два писателя не смогут одновременно записать данные и создать противоречивое состояние — Iceberg обнаружит конфликт при коммите и откатит одну из транзакций. Это критично для пайплайнов, где несколько джобов пишут в одну таблицу параллельно.
Time Travel и откаты. Каждый снепшот — это неизменяемый снимок состояния таблицы. Можно запросить данные на любой момент времени или по номеру снепшота. Совершили ошибочную вставку? Достаточно откатить указатель текущего снепшота — без ручного удаления файлов. Это работает как «Ctrl+Z» для всей таблицы.
Эволюция схемы без простоя. Добавить столбец, переименовать его или изменить тип — всё это делается без перезаписи данных. Iceberg хранит схему отдельно от файлов данных, поэтому изменение схемы — это просто новая запись в метаданных. Старые файлы Parquet продолжают читаться корректно, потому что Iceberg сопоставляет столбцы по идентификаторам, а не по именам.
Скрытое партиционирование. В Hive вы обязаны знать структуру каталогов и явно указывать партиции в запросах. Iceberg скрывает это: вы пишете WHERE event_date = '2024-01-15', а движок сам определяет, какие файлы читать. При этом Iceberg поддерживает трансформации партиционирования — например, bucket(16, user_id) или days(event_ts) — без создания физической иерархии каталогов.
Data skipping через метаданные. Каждый manifest file хранит статистику (min/max, количество null) по каждому столбцу в каждом файле данных. Движок запросов может отсечь ненужные файлы ещё до их чтения. Как отмечается в статье на Хабр, если установить порядок записи (WRITE ORDERED BY), то min/max границы становятся компактными, и запрос с фильтром id < 196470 прочитает один файл вместо всей таблицы.
Совместимость с экосистемой. Iceberg поддерживают Apache Spark, Trino, Flink, Dremio, Starburst, Athena и десятки других движков. Один и тот же набор данных можно читать из Spark-джоба и из Trino-запроса аналитика — без конвертации.
Где Iceberg проигрывает
Сложность начальной настройки. Чтобы начать использовать Iceberg, нужен каталог — внешний сервис (Hive Metastore, AWS Glue, REST Catalog, Nessie), который хранит указатели на метаданные таблиц. Это дополнительный компонент инфраструктуры, который нужно развернуть, мониторить и поддерживать. Для небольших проектов это может быть избыточно.
Накладные расходы на метаданные. Каждая запись создаёт новый снепшот, manifest list и manifest file. При интенсивной стриминговой записи (тысячи мелких вставок в минуту) метаданные разрастаются, и чтение таблицы замедляется, потому что движку нужно обработать все манифесты. Решение — регулярный compaction метаданных и файлов данных, но это дополнительная операционная нагрузка.
Отсутствие вторичных индексов. Iceberg не хранит B-tree или bitmap-индексы. Data skipping работает только по статистикам файлов (min/max). Если ваш запрос фильтрует по столбцу с высокой кардинальностью и данные не отсортированы — вы получите полное сканирование. Некоторые движки (например, Trino через бloom filter) добавляют свои механизмы, но это не часть спецификации Iceberg.
Merge-on-Read откладывает стоимость на чтение. Стратегия MoR позволяет быстро записывать обновления и удаления через delete-файлы, но при чтении движок должен применить эти удаления поверх основных данных. Как подчёркивает Хабр-статья, с форматом v3 появились deletion vectors (битмаски), которые ускоряют этот процесс, но стоимость чтения всё равно выше, чем у статических таблиц.
Зависимость от зрелости движка. Спецификация Iceberg — это стандарт, но каждый движок реализует его по-разному. Spark поддерживает Iceberg наиболее полно, Trino — хорошо, Flink — активно развивается. Если ваша команда использует движок с неполной поддержкой (например, старые версии Trino), вы столкнётесь с ограничениями.
Сравнение с альтернативами
| Критерий | Iceberg | Delta Lake | Hive (ACID) | |---|---|---|---| | Открытый стандарт | Да (Apache Foundation) | Частично (Databricks) | Да (Apache Foundation) | | Time Travel | Да, по снепшотам | Да, по версиям | Ограниченно | | Эволюция схемы | Идентификаторы столбцов | Имена столбцов | Через SerDe | | Партиционирование | Скрытое, с трансформациями | Скрытое | Явное (каталоги) | | Поддержка движков | Широкая | Преимущественно Spark | Широкая | | Стриминг | Flink, Spark Structured Streaming | Spark Structured Streaming | Нет нативной |
Delta Lake проще в настройке, если вы уже на Databricks, но привязывает вас к экосистеме одного вендора. Hive ACID работает, но медленно развивается и не поддерживает скрытое партиционирование. Iceberg занимает позицию «открытого стандарта с максимальной совместимостью».
Когда стоит выбирать Iceberg
Iceberg — оптимальный выбор, когда у вас есть несколько движков, работающих с одними данными; когда нужен time travel для аудита или отладки; когда данные растут и партиционирование Hive перестаёт масштабироваться; когда вы строите lakehouse-архитектуру и хотите ACID-гарантии без привязки к вендору.
Если же у вас небольшой объём данных, один движок (например, только Spark на Databricks) и нет требований к time travel — Delta Lake может оказаться проще. Если данные статичны и записываются раз в день без обновлений — обычный Parquet с каталогом вполне достаточен.
Ключевой вывод: Iceberg решает проблему управления данными на data lake, а не проблему хранения. Если ваша боль — целостность, версионирование, эволюция схемы и совместимость движков — Iceberg оправдает инвестиции в инфраструктуру. Если боль в другом месте — начните с более простого решения.