DuckLake против Iceberg и Delta Lake
Apache Iceberg и Delta Lake — два самых распространённых лейкхаус-формата.
Выбор Table Format: Delta Lake vs Iceberg vs Hudi vs Paimon Iceberg: снимки, коммиты и time travelTrino: time travel в Iceberg — FOR VERSION AS OF Iceberg вырос в Netflix и стал отраслевым стандартом с широкой поддержкой движков; Delta Lake вырос в Databricks и тесно связан с экосистемой Spark. Оба решают одну задачу: превратить файлы Parquet на объектном хранилище в таблицы с ACID и версионированием.
DuckLake — поздний игрок (версия 1.0 — апрель 2026) с одним радикальным архитектурным отличием: метаданные в SQL-каталоге, а не в файлах. Этот урок — честное сравнение трёх форматов. Не «DuckLake лучше всех», а где архитектура метаданных-в-СУБД даёт реальное преимущество, где она оборачивается компромиссом, и по каким критериям выбирать формат.
Главная развилка: где живут метаданные
Все три формата кладут данные одинаково — иммутабельными файлами Parquet на объектном хранилище. Расходятся они в том, где хранятся метаданные таблицы.
У Iceberg метаданные — это иерархия файлов: корневой metadata.json, под ним манифест-листы, под ними манифесты, и всё это в Avro/JSON на объектном хранилище. Поверх обязателен внешний catalog (REST catalog, Hive Metastore, AWS Glue и т.п.) — но он в классической схеме хранит лишь указатель «где сейчас актуальный metadata.json», а тело метаданных всё равно в файлах.
У Delta Lake метаданные — это транзакционный лог: папка _delta_log рядом с данными, в ней упорядоченные JSON-файлы коммитов и периодические Parquet-чекпойнты лога. Чтобы узнать текущее состояние таблицы, движок проигрывает лог.
У DuckLake метаданные — это просто таблицы в реляционной СУБД. На объектном хранилище нет ни одного файла метаданных, только Parquet с данными.
Где метаданные-в-СУБД выигрывают
Из этой развилки следуют конкретные преимущества DuckLake.
Скорость планирования запроса. У файловых форматов, чтобы понять, какие data-файлы читать, нужно пройти цепочку файлов метаданных — несколько последовательных round-trip к объектному хранилищу, у которого латентность одного запроса — десятки миллисекунд. DuckLake делает один SQL-запрос к каталогу и сразу получает список нужных файлов с pruning по статистике. На таблицах с большим числом файлов разница в латентности планирования заметная.
Кросс-табличные транзакции. Iceberg и Delta атомарны в пределах одной таблицы: коммит — это атомарная замена указателя на состояние этой таблицы. Согласованно поменять несколько таблиц одним атомарным актом нечем. У DuckLake коммит — это транзакция каталожной СУБД, и её атомарность покрывает изменения любого числа таблиц сразу.
Проблема мелких файлов. У файловых форматов каждая мелкая запись порождает мелкий data-файл и новые файлы метаданных; нужна регулярная compaction. DuckLake через data inlining пишет мелкие правки строками в каталог, не создавая файлов вовсе.
Простота метаданных-операций. «Сколько снапшотов у таблицы», «какие файлы добавлены между версиями», «суммарный размер таблицы» — у DuckLake это обычные SQL-запросы к каталогу. У файловых форматов это обход файлов метаданных.
| Критерий | Iceberg / Delta (файлы) | DuckLake (СУБД) |
|---|---|---|
| Планирование запроса | Цепочка round-trip к хранилищу | Один SQL-запрос к каталогу |
| Атомарность | В пределах одной таблицы | Несколько таблиц в одной транзакции |
| Мелкие правки | Плодят мелкие файлы, нужна compaction | Inlining в каталог |
| Запросы к метаданным | Обход файлов метаданных | Обычный SQL |
Где это компромисс, а не победа
Архитектура метаданных-в-СУБД честно платит за свои преимущества. Игнорировать минусы было бы нечестным сравнением.
Каталог — это компонент, который надо иметь и поддерживать. У файловых форматов метаданные лежат там же, где данные, — на объектном хранилище, которое и так есть. У DuckLake нужна работающая СУБД под каталог. Для PostgreSQL-варианта это полноценная база, которую кто-то администрирует, бэкапит, мониторит. (Для SQLite/DuckDB-каталога это просто файл — компромисс мягче, но и модель конкуренции у них ограниченнее.)
Каталог — потенциальная точка отказа и узкое место. Все запросы на планирование идут в каталог. Если каталожная СУБД недоступна — недоступен весь лейкхаус. У файловых форматов планирование опирается только на объектное хранилище. Каталог надо масштабировать и держать доступным под нагрузкой.
Зрелость и экосистема. Iceberg существует с 2017 года, это де-факто отраслевой стандарт: его читают и пишут Spark, Trino, Flink, Snowflake, BigQuery, множество движков. Delta Lake глубоко интегрирован с экосистемой Databricks/Spark. DuckLake вышел в 1.0 в апреле 2026 — он молодой. Список движков, умеющих с ним работать, растёт (DuckDB, Apache DataFusion, Spark, Trino, Pandas), но он короче, чем у Iceberg, и сама экосистема инструментов пока тоньше.
Главный компромисс DuckLake — это смена характера зависимости. Файловые форматы зависят только от объектного хранилища. DuckLake добавляет зависимость от каталожной СУБД: её доступность, её бэкап, её масштабирование становятся вашей ответственностью. Преимущества DuckLake реальны, но они не бесплатны — вы меняете «обход файлов» на «эксплуатацию базы данных».
Совместимость и взаимодействие
Форматы не полностью изолированы. На уровне данных все три используют Parquet, и DuckLake целенаправленно держит свои data-файлы и вспомогательные структуры совместимыми с Iceberg v3 — это касается и формата Parquet-файлов, и подхода к deletion vectors через Puffin-файлы. Цель — чтобы один и тот же набор data-файлов потенциально могли читать инструменты обеих экосистем, а миграция между форматами не означала перезапись всех данных.
DuckDB при этом умеет читать и сами Iceberg- и Delta-таблицы — через расширения iceberg и delta. То есть DuckDB как движок не заперт в DuckLake: он работает со всеми тремя форматами. Это снижает риск выбора — переход на DuckLake не отрезает от уже существующих Iceberg/Delta-данных.
-- Один движок DuckDB читает все три формата
-- DuckLake через расширение ducklake
ATTACH 'ducklake:postgres:dbname=lake' AS lake (DATA_PATH 's3://bucket/lake/');
SELECT count(*) FROM lake.orders;
-- Iceberg-таблица через расширение iceberg
SELECT count(*) FROM iceberg_scan('s3://bucket/iceberg/orders');
-- Delta-таблица через расширение delta
SELECT count(*) FROM delta_scan('s3://bucket/delta/orders');
Как выбирать
Сведём в практическое правило.
| Ситуация | Разумный выбор |
|---|---|
| Уже есть Iceberg/Delta и большая экосистема движков | Оставаться на нём, DuckLake выгоды не перевесят миграцию |
| Тесная привязка к Spark/Databricks | Delta Lake — родная экосистема |
| Нужен максимально широкий список движков-читателей | Iceberg — отраслевой стандарт |
| Лейкхаус с DuckDB в центре, частые мелкие апдейты | DuckLake — inlining и быстрое планирование к месту |
| Нужны кросс-табличные транзакции | DuckLake — единственный из трёх даёт их из коробки |
| Локальный или командный лейкхаус без тяжёлой инфраструктуры | DuckLake с SQLite/PostgreSQL-каталогом |
Главный принцип: формат выбирается под экосистему и характер нагрузки, а не по «новизне». DuckLake силён там, где есть мелкие частые правки, нужны кросс-табличные транзакции и низкая латентность планирования, а DuckDB — основной движок. Iceberg силён широтой поддержки и зрелостью. Delta — связкой со Spark. А поскольку DuckDB читает все три, выбор DuckLake не запирает: можно начать с него и при необходимости работать с Iceberg/Delta тем же движком.
Попробуй сам
Понадобится DuckDB 1.5.x. Для Iceberg/Delta-части достаточно публичных демо-таблиц или собственных, созданных через соответствующие расширения.
Задания:
- Создайте локальный DuckLake-лейкхаус и таблицу. Затем выполните
FROM lake.snapshots();иFROM lake.table_changes('таблица', 0, 1);. Зафиксируйте, что метаданные-операции — это обычные SQL-запросы. - Сформулируйте письменно, как вы получили бы тот же ответ («какие файлы добавлены между версиями») в Iceberg: какие файлы метаданных пришлось бы обойти.
- Откройте папку данных DuckLake-лейкхауса и папку любой Iceberg-таблицы. Сравните: в Iceberg найдите файлы
metadata.json, манифест-листы, манифесты; в DuckLake убедитесь, что файлов метаданных на хранилище нет вообще. - Составьте таблицу решения для трёх своих гипотетических проектов (например: «аналитика поверх существующего Iceberg-озера», «новый лейкхаус для команды на DuckDB», «пайплайн на Databricks») и обоснуйте выбор формата для каждого.
Delta Lake: transaction log как альтернатива manifest-иерархии