Learning Platform
Глоссарий Troubleshooting
Урок 16.03 · 23 мин
Средний
ducklakelakehousemetadata-catalogparquet

DuckLake: лейкхаус-формат с метаданными в SQL-каталоге

Лейкхаус (lakehouse) — это попытка соединить дешёвое объектное хранилище data lake с транзакционными гарантиями data warehouse. Данные лежат файлами Parquet в S3 или аналоге, а сверху работает table format, который превращает россыпь файлов в таблицы со схемой, версиями и ACID. Так устроены Apache Iceberg и Delta Lake.

У всех классических table format есть общая архитектурная черта: метаданные тоже лежат файлами на объектном хранилище — JSON-манифесты, Avro-списки, snapshot-файлы. DuckLake делает иначе. Это лейкхаус-формат от DuckDB Labs, который держит все метаданные в реляционной SQL-базе, а файлами на объектном хранилище оставляет только сами данные. Это маленькое на словах решение меняет почти всё: атомарность транзакций, скорость операций над метаданными, простоту реализации. В этом уроке разберём устройство DuckLake, причину «метаданные в SQL» и три поддерживаемых бэкенда каталога.

DuckLake достиг версии 1.0 13 апреля 2026 года — это production-ready релиз с гарантией обратной совместимости формата.


Проблема метаданных-в-файлах

Чтобы понять, зачем DuckLake, нужно увидеть, что болит у форматов с файловыми метаданными. Когда метаданные таблицы — это набор файлов на объектном хранилище, каждая операция чтения превращается в цепочку обращений: сначала прочитать корневой указатель, по нему — файл текущего снапшота, по нему — манифест-лист, по нему — манифесты, и только потом узнать, какие data-файлы вообще нужно открыть.

Чтение таблицы в формате с файловыми метаданными
Корневой указательФайл, указывающий на текущую версию таблицы. Первое обращение к объектному хранилищу.
Файл снапшотаJSON со списком манифест-листов и схемой. Второе сетевое обращение.
Манифест-лист и манифестыAvro-файлы со списком data-файлов и их статистикой. Ещё несколько сетевых обращений.
Data-файлы ParquetТолько теперь известно, какие именно файлы Parquet читать под запрос.

Из этой схемы вытекают три конкретные боли. Первая — латентность планирования: чтобы узнать, какие файлы читать, нужно несколько последовательных round-trip к объектному хранилищу, а у S3 латентность каждого запроса — десятки миллисекунд. Вторая — атомарность только в пределах одной таблицы: смена «текущего» снапшота — это атомарная замена одного указателя, и согласованно поменять сразу несколько таблиц нечем; кросс-табличной транзакции нет. Третья — проблема мелких файлов: каждая мелкая правка порождает новые мелкие data-файлы и новые метаданные, число файлов растёт, чтение деградирует, и нужна отдельная процедура compaction.

Корень всех трёх проблем один: объектное хранилище — это key-value-склад больших блобов, оно отлично хранит данные, но плохо подходит под метаданные, которым нужны быстрые точечные запросы и транзакции.


Идея DuckLake: метаданные туда, где им место

DuckLake исходит из простого наблюдения. Метаданные таблиц — это по своей природе реляционные данные: список таблиц, список колонок, список снапшотов, список data-файлов с их статистикой, связи между ними. А для реляционных данных с транзакциями и быстрыми запросами уже сорок лет существует идеальный инструмент — реляционная СУБД.

Поэтому DuckLake разделяет лейкхаус на два чётко разных слоя:

Два слоя DuckLake
SQL-каталогРеляционная СУБД хранит ВСЕ метаданные: таблицы, колонки, снапшоты, список data-файлов, статистику, deletion-векторы. Быстрые запросы и транзакции дают СУБД.
ссылается на
Объектное хранилищеS3, GCS, Azure Blob или локальная папка. Хранит только сами данные — иммутабельные файлы Parquet. Никаких метаданных здесь нет.

Каталог — это набор обычных таблиц в SQL-базе. В них записано всё: какие в лейкхаусе есть таблицы и колонки, какие существуют снапшоты, какие data-файлы относятся к каждому снапшоту, какая у каждого файла статистика (min/max по колонкам, число строк). Сами Parquet-файлы лежат на объектном хранилище и являются иммутабельными — их не редактируют, только добавляют новые.

Что это даёт по сравнению с файловыми метаданными:

  • Планирование запроса — один SQL-запрос к каталогу. Вместо цепочки round-trip к S3 движок делает один запрос к базе: «дай мне data-файлы таблицы X для снапшота N, у которых min/max по колонке date пересекается с фильтром». СУБД возвращает готовый список с pruning по статистике.
  • Атомарность сразу по многим таблицам. Коммит в DuckLake — это обычная транзакция в каталожной СУБД. А реляционная транзакция атомарна по определению: можно согласованно поменять метаданные пяти таблиц одним коммитом. Кросс-табличная ACID-транзакция получается бесплатно, из ACID самой СУБД.
  • Мелкие правки не плодят мелкие файлы. Раз каталог — это база, маленькое изменение можно записать прямо в строки каталога, не создавая крошечный Parquet-файл. Этот механизм — data inlining — разберём в следующем уроке.

Архитектура: спецификация, реализация, бэкенды

DuckLake устроен как три отдельных вещи, и их полезно не путать.

Спецификация — это открытый документ, описывающий формат: какие таблицы должны быть в каталоге, какая у них схема, как кодируются снапшоты и ссылки на файлы. Спецификация не привязана к DuckDB; по ней может быть написан любой совместимый клиент.

Эталонная реализация — это расширение ducklake для DuckDB. Оно реализует спецификацию: умеет создавать лейкхаус, читать и писать таблицы, делать снапшоты. Расширение ducklake уже входит в число самых скачиваемых core-расширений DuckDB.

Бэкенды каталога — это конкретные СУБД, в которых физически живёт каталог. И здесь важная точность: DuckLake поддерживает ровно три бэкенда.

Бэкенд каталогаХарактерКогда выбирать
SQLiteEmbedded, файл, один писательЛокальная разработка, однопользовательский лейкхаус, эксперименты
PostgreSQLСетевой, настоящий multi-writerКоманда, продакшн, несколько процессов пишут параллельно
DuckDBSelf-referential, embeddedСамодостаточный лейкхаус: DuckDB и движок, и каталог

Других бэкендов нет. Каталогом DuckLake не может быть MySQL или произвольная СУБД — список закрытый и состоит из SQLite, PostgreSQL и DuckDB. Требования к бэкенду — он должен говорить на SQL, поддерживать первичные ключи и уметь хранить таблицы постоянно; этим трём СУБД эти требования соответствуют, и именно они поддержаны.

WARNING

Выбор бэкенда — это и выбор модели конкуренции записи. SQLite — embedded-файл с одним писателем: для локального лейкхауса отлично, но команде не подходит. PostgreSQL — сетевая СУБД с настоящим multi-writer: несколько процессов параллельно коммитят в один лейкхаус. DuckDB-каталог даёт полностью самодостаточный лейкхаус, где один и тот же движок и исполняет запросы, и хранит метаданные. Под продакшн с несколькими писателями берут PostgreSQL.


Как это выглядит на практике

Создание DuckLake-лейкхауса — это ATTACH с указанием бэкенда каталога и места для данных. Сначала простейший случай — каталог в SQLite, данные в локальной папке:

-- Установить и подключить расширение DuckLake
INSTALL ducklake;
LOAD ducklake;

-- Создать лейкхаус: каталог в SQLite-файле, данные Parquet в папке
ATTACH 'ducklake:sqlite:catalog.sqlite' AS lake (DATA_PATH 'lake_data/');
USE lake;

-- Дальше — обычный SQL. Таблица создаётся в лейкхаусе.
CREATE TABLE orders AS
  SELECT * FROM 'raw/orders.parquet';

-- Результат:
-- 842_119 строк. В lake_data/ появились Parquet-файлы,
-- а в catalog.sqlite — метаданные таблицы и первый снапшот.

После этого в SQLite-файле catalog.sqlite лежат метаданные, в папке lake_data/ — Parquet-файлы с данными. Можно заглянуть в каталог и увидеть, что метаданные — это обычные строки в обычных таблицах:

-- Список снапшотов лейкхауса — обычная таблица в каталоге
FROM lake.snapshots();
-- snapshot_id | snapshot_time       | schema_version
-- ------------+---------------------+---------------
-- 0           | 2026-05-20 09:14:02 | 0
-- 1           | 2026-05-20 09:14:05 | 1

Для команды каталог переносят в PostgreSQL — меняется только строка подключения, SQL остаётся тем же:

-- Тот же лейкхаус, но каталог в PostgreSQL, данные на S3
ATTACH 'ducklake:postgres:dbname=lakehouse host=db.internal' AS lake
  (DATA_PATH 's3://my-bucket/lake/');

Существенно, что для пользователя DuckLake выглядит как обычная база DuckDB. Вы делаете CREATE TABLE, INSERT, SELECT, оконные функции, friendly SQL — всё как всегда. То, что под капотом данные — это Parquet на объектном хранилище, а метаданные — строки в SQL-каталоге, спрятано за расширением ducklake. Лейкхаус-формат с серьёзными гарантиями подключается одной строкой ATTACH.


Попробуй сам

Понадобится DuckDB 1.5.x. Расширение ducklake ставится из core-репозитория.

Задания:

  1. Выполните INSTALL ducklake; LOAD ducklake;, затем создайте локальный лейкхаус с каталогом в SQLite: ATTACH 'ducklake:sqlite:cat.sqlite' AS lake (DATA_PATH 'lake_data/');. Создайте в нём таблицу из любого CSV или через range().
  2. Посмотрите на файловую раскладку: какие файлы появились в папке lake_data/ и что лежит в cat.sqlite. Откройте cat.sqlite отдельным подключением DuckDB или SQLite и убедитесь, что метаданные — это обычные таблицы.
  3. Выполните FROM lake.snapshots(); и FROM lake.table_info(); (или аналогичные служебные функции лейкхауса) — посмотрите, как каталог описывает таблицы и снапшоты.
  4. Создайте отдельный лейкхаус с каталогом-бэкендом DuckDB вместо SQLite. Сравните, что изменилось в строке ATTACH, и сформулируйте, почему для команды из нескольких писателей ни SQLite, ни DuckDB-каталог не подойдут, а PostgreSQL — подойдёт.

Iceberg: иерархия метаданных — metadata file, manifest list, manifests
Проверка знанийKnowledge check
Чем DuckLake принципиально отличается от Iceberg и Delta Lake по части метаданных, какие три проблемы это решает и какие бэкенды каталога он поддерживает?
ОтветAnswer
DuckLake — это открытый лейкхаус-формат от DuckDB Labs, который держит ВСЕ метаданные таблиц в реляционной SQL-базе (каталоге), а на объектном хранилище оставляет только сами данные — иммутабельные файлы Parquet. Iceberg и Delta Lake, наоборот, хранят метаданные тоже файлами на объектном хранилище — JSON-манифестами, Avro-списками, snapshot-файлами. Перенос метаданных в СУБД решает три проблемы файлового подхода. Первая — латентность планирования: вместо цепочки последовательных round-trip к S3 (корневой указатель, файл снапшота, манифесты) движок делает один SQL-запрос к каталогу и сразу получает список нужных data-файлов с pruning по статистике. Вторая — атомарность: коммит в DuckLake это обычная транзакция каталожной СУБД, а реляционная транзакция атомарна по определению, поэтому можно согласованно поменять метаданные сразу нескольких таблиц одним коммитом — кросс-табличная ACID-транзакция получается из ACID самой СУБД. Третья — проблема мелких файлов: маленькую правку можно записать прямо в строки каталога, не создавая крошечный Parquet-файл (механизм data inlining). DuckLake поддерживает ровно три бэкенда каталога: SQLite (embedded, один писатель — для локальной разработки), PostgreSQL (сетевой, настоящий multi-writer — для команды и продакшна) и DuckDB (self-referential, самодостаточный лейкхаус). MySQL и другие СУБД каталогом быть не могут — список закрытый. DuckLake достиг production-ready версии 1.0 13 апреля 2026 года.

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

Результат: 0 из 0
Концептуальный
Вопрос 1 из 4. В чём состоит ключевое архитектурное решение DuckLake?

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

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

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

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