Единый Lakehouse connector: Hive, Iceberg, Delta и Hudi через один каталог
К этому моменту модуля мы разобрали три формата таблиц по отдельности: Hive с метаданными в Metastore, Delta с transaction log, Iceberg с деревом снапшотов. В реальной организации они сосуществуют — и это создаёт неудобство, которое долго принимали как данность. Trino release 477 (сентябрь 2025) принёс решение: единый Lakehouse connector, который читает таблицы Hive, Iceberg, Delta и Hudi через один каталог. Этот завершающий урок модуля объясняет, какую конкретную проблему решает объединённый коннектор, как он устроен и когда его выбирать.
Проблема: четыре формата — четыре каталога
Вспомним, как устроена работа с форматами до Lakehouse-коннектора. Каждый формат таблиц — это свой коннектор Trino: hive, iceberg, delta_lake, hudi. А каждый коннектор требует своего каталога Trino — отдельного *.properties-файла. Организация, у которой есть и Hive-таблицы, и Iceberg, и Delta, вынуждена держать минимум три отдельных каталога.
В чём конкретно боль. Все эти таблицы физически лежат в одном и том же object storage, часто под общим metastore, и зачастую даже в соседних схемах. Логически это «наши таблицы данных». Но из-за того, что формат таблиц определяет коннектор, а коннектор требует каталога, эти логически близкие таблицы оказываются в разных каталогах Trino, и обращаться к ним нужно по разным префиксам.
Тяжелее всего это бьёт по федеративным запросам. Допустим, fact-таблица событий — в Iceberg, а dimension-таблица справочника — в Delta (так бывает: разные команды, разные пайплайны, разные исторические решения). Чтобы их сджойнить, в запросе приходится явно писать два разных каталога:
-- ДО Lakehouse-коннектора: Iceberg и Delta — в РАЗНЫХ каталогах,
-- хотя данные лежат в одном object storage под одним metastore
SELECT e.event_type, d.category_name, count(*) AS cnt
FROM iceberg.analytics.events AS e
JOIN delta.reference.categories AS d
ON e.category_id = d.category_id
GROUP BY e.event_type, d.category_name;
Запрос работает — Trino умеет джойнить между каталогами. Но налицо искусственное усложнение: пользователь обязан помнить, какая таблица в каком формате, и держать в голове соответствие «формат -> каталог». Формат хранения — это деталь реализации таблицы, а она протекла в то, как пишется запрос. И при миграции таблицы из одного формата в другой меняется её префикс каталога — а значит, ломаются все запросы и витрины, которые на неё ссылались.
Lakehouse connector: один каталог на все форматы
Lakehouse connector (connector.name=lakehouse), появившийся в Trino release 477 (сентябрь 2025), объединяет функциональность четырёх коннекторов — Hive, Iceberg, Delta Lake и Hudi — в одном. Один каталог Trino на основе этого коннектора видит и читает таблицы всех четырёх форматов.
Ключевая механика — автоопределение формата. Когда запрос обращается к таблице, Lakehouse-коннектор смотрит в метаданные таблицы и определяет её формат: есть ли у неё дерево метаданных Iceberg, поддиректория _delta_log/ Delta, признаки Hive или Hudi. Дальше коннектор применяет соответствующую логику чтения. Для пользователя это прозрачно: он пишет lakehouse.schema.table, не указывая и не зная формат. Формат таблицы становится тем, чем и должен быть, — внутренней деталью таблицы, а не частью её адреса.
# etc/catalog/lakehouse.properties — один каталог на все форматы
connector.name=lakehouse
hive.metastore=thrift
hive.metastore.uri=thrift://hms:9083
fs.native-s3.enabled=true
s3.endpoint=http://minio:9000
s3.path-style-access=true
Тот же федеративный запрос с единым каталогом — формат таблиц больше не упоминается:
-- ПОСЛЕ: один каталог lakehouse, формат определяется автоматически.
-- events — Iceberg, categories — Delta, но запрос об этом не знает.
SELECT e.event_type, d.category_name, count(*) AS cnt
FROM lakehouse.analytics.events AS e
JOIN lakehouse.reference.categories AS d
ON e.category_id = d.category_id
GROUP BY e.event_type, d.category_name;
-- event_type | category_name | cnt
-- ------------+---------------+-------
-- purchase | electronics | 14820
-- view | electronics | 90341
-- purchase | books | 6210
Запрос стал чище и, что важнее, устойчивее к миграции. Если завтра categories переведут из Delta в Iceberg — её адрес lakehouse.reference.categories не изменится. Запрос продолжит работать без правок: Lakehouse-коннектор просто определит новый формат и применит другую логику чтения. Связь между запросом и форматом хранения разорвана.
Lakehouse-коннектор появился в Trino release 477 (сентябрь 2025) — это относительно свежая возможность. Под капотом он переиспользует ту же отлаженную логику, что и отдельные коннекторы Hive, Iceberg, Delta и Hudi: это не новая реализация форматов, а объединяющий слой над уже существующими. Поддерживаются метасторы Hive Metastore и AWS Glue, хранилища S3 и S3-совместимые, GCS, Azure Blob, HDFS.
Как это работает с записью и DDL
Чтение через автоопределение формата понятно. Но что с созданием таблиц — у Lakehouse-коннектора один каталог, а форматы разные? CREATE TABLE указывает желаемый формат таблицы свойством, и коннектор создаёт таблицу именно в нём:
-- Создать Iceberg-таблицу через Lakehouse-коннектор
CREATE TABLE lakehouse.analytics.events (
event_id BIGINT,
category_id BIGINT,
event_type VARCHAR,
event_ts TIMESTAMP(6)
)
WITH (type = 'ICEBERG', partitioning = ARRAY['day(event_ts)']);
-- Создать Delta-таблицу через тот же каталог
CREATE TABLE lakehouse.reference.categories (
category_id BIGINT,
category_name VARCHAR
)
WITH (type = 'DELTA');
Дальше каждая таблица обслуживается процедурами своего формата — Iceberg-таблица знает expire_snapshots, Delta-таблица знает vacuum. Lakehouse-коннектор не размывает различия форматов: time travel, обслуживание, специфика DML у каждой таблицы остаются её родными. Коннектор лишь убирает одно — необходимость держать четыре каталога и упоминать формат в адресе таблицы. Все знания из этого и прошлого модулей — снапшоты Iceberg, transaction log Delta, ACID Hive — остаются в силе; меняется только то, через сколько каталогов вы к ним обращаетесь.
Полезно зафиксировать, что именно остаётся специфичным для формата даже под единым коннектором, чтобы не возникло иллюзии «теперь всё одинаково». Time travel: Iceberg и Delta его поддерживают, у обычной Hive-таблицы его нет — единый каталог этого не меняет. Обслуживание: процедуры разные по именам и механике — expire_snapshots против vacuum, optimize у обоих, но за ним стоят разные модели метаданных. Row-level DML: у Iceberg v2 и Delta он полноценный, у обычной Hive-таблицы — нет, у транзакционной Hive — только в ORC. То есть, перейдя на Lakehouse-коннектор, инженер по-прежнему обязан знать, в каком формате создана конкретная таблица, чтобы понимать, что с ней можно делать. Коннектор унифицирует доступ, но не возможности.
Отсюда практический совет по миграции на Lakehouse-коннектор. Переход не требует переписывать данные — форматы таблиц остаются прежними, меняется лишь каталог, через который к ним обращаются. Но если на старые каталоги (iceberg.*, delta.*) ссылаются существующие запросы и витрины, простая замена каталога на lakehouse.* затронет их адресацию. Поэтому переход обычно делают постепенно: новые таблицы и запросы — сразу через lakehouse, старые — мигрируют по мере того, как их всё равно трогают. Срочности нет: отдельные коннекторы Hive, Iceberg и Delta никуда не делись и продолжают работать параллельно с Lakehouse-коннектором.
Когда выбирать Lakehouse-коннектор
| Ситуация | Рекомендация |
|---|---|
| Новый проект, в storage будут таблицы разных форматов | Lakehouse-коннектор: один каталог с самого начала |
| Уже есть отдельные каталоги hive/iceberg/delta, всё работает | Можно мигрировать на Lakehouse постепенно; срочности нет |
| В организации только один формат (например, только Iceberg) | Достаточно отдельного коннектора; объединять нечего |
| Часты федеративные join между таблицами разных форматов | Lakehouse-коннектор заметно упрощает запросы |
| Планируются миграции таблиц между форматами | Lakehouse-коннектор: адрес таблицы переживёт смену формата |
Практический вывод. Lakehouse-коннектор не привносит новых возможностей работы с самими форматами — снапшоты, transaction log, ACID он не меняет. Его ценность — устранение организационного трения: один каталог вместо четырёх, формат как внутренняя деталь таблицы, а не часть её адреса, и устойчивость запросов к миграции между форматами. Для организации со смешанным lakehouse это ощутимое упрощение; для моноформатной — необязательная опция. Это логичный финал линии «открытые форматы поверх object storage»: сначала форматы дали таблицам гарантии, теперь единый коннектор убрал швы между ними.
dbt-trino: Lakehouse connector и dbt-моделиПопробуй сам
В песочнице настройте каталог lakehouse (connector.name=lakehouse, общий metastore, MinIO). Упражнение первое: создайте через этот один каталог две таблицы разных форматов — одну с type = 'ICEBERG', другую с type = 'DELTA' — и загрузите в каждую данные. Упражнение второе: выполните JOIN между этими двумя таблицами одним запросом и убедитесь, что формат в запросе нигде не упоминается. Затем выполните SHOW TABLES FROM lakehouse.<schema> и обратите внимание, что таблицы обоих форматов видны в одном каталоге как равноправные. Упражнение третье на родную механику: примените ALTER TABLE EXECUTE optimize к обеим таблицам, затем процедуру удаления истории — expire_snapshots к Iceberg-таблице и vacuum к Delta-таблице. Письменно объясните: что именно Lakehouse-коннектор унифицирует, а что у каждой таблицы остаётся специфичным для её формата, и почему запрос с обращением к lakehouse.schema.table переживёт миграцию этой таблицы из Delta в Iceberg.