Обзор экосистемы коннекторов
Trino поставляется с десятками коннекторов, и за каждым стоит источник со своей природой. Реляционная СУБД, файл на object storage, топик Kafka — это принципиально разные модели данных. Один коннектор читает строки через SQL по сети, другой парсит колоночные файлы, третий вычитывает поток сообщений. Эти различия не косметические: они определяют, что от источника можно ждать по производительности и по семантике.
Этот урок даёт карту экосистемы по четырём большим категориям: object storage / lakehouse, RDBMS, NoSQL, streaming. Цель — не заучить список, а понять, чем категории отличаются и как выбор источника влияет на запрос.
Четыре категории источников
Категории различаются по трём осям, которые стоит держать в голове: умеет ли источник параллелить чтение, насколько богатый pushdown коннектор может реализовать, и есть ли у источника собственная статистика для оптимизатора. Дальше пройдём по категориям именно с этой меркой.
Object storage и lakehouse
Это категория, ради которой Trino чаще всего и разворачивают. Данные лежат файлами на object storage — S3, GCS, Azure Blob, HDFS. Сами по себе файлы это просто Parquet или ORC. Чтобы набор файлов стал «таблицей» с историей изменений и схемой, нужен табличный формат: Hive, Iceberg, Delta Lake или Hudi. Табличный формат хранит метаданные — какие файлы входят в таблицу, какая у неё схема, какие были снапшоты.
Коннекторы этой категории:
| Коннектор | Что это |
|---|---|
| Hive | Старейший формат: метаданные в Hive Metastore, данные в ORC/Parquet/других форматах |
| Iceberg | Современный открытый формат таблиц: снапшоты, time travel, schema evolution |
| Delta Lake | Формат от Databricks: transaction log, deletion vectors, change data feed |
| Hudi | Формат с акцентом на upsert и инкрементальную обработку |
| Lakehouse | Единый коннектор, объединяющий Hive, Iceberg, Delta Lake и Hudi в одном catalog |
Семантика этой категории: чтение хорошо параллелится (файлы и row-group-и становятся splits — много splits, много задач), pushdown богатый (для Parquet/ORC работает predicate и projection pushdown вплоть до пропуска row-group по min/max), статистика обычно есть (Iceberg и Delta поддерживают статистику и обновляют её при записи).
Iceberg, Delta Lake и Hive — это НЕ базы данных. Это форматы таблиц поверх файлов в object storage. Их “метаданные” — список файлов, схема, снапшоты — лежат в Metastore или в специальном каталоге. Trino через коннектор читает эти метаданные, чтобы понять, что таблица собой представляет, а затем читает сами файлы данных.
Отдельно стоит упомянуть, что Trino перешёл на нативную файловую систему для object storage — собственные реализации доступа к S3, Azure, GCS. Старый Hadoop-based слой доступа удалён в релизе 481, так что актуальные кластеры используют только нативную ФС.
RDBMS: реляционные источники через JDBC
Вторая большая категория — реляционные СУБД: PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, Redshift, ClickHouse, SingleStore, Snowflake, BigQuery, DuckDB, Exasol, Ignite. Большинство из них Trino читает через JDBC, и у этой категории своя характерная семантика.
Параллелизм чтения здесь по умолчанию ограничен. Реляционная таблица для JDBC-коннектора обычно становится одним split — Trino открывает одно соединение и тянет результат потоком. В отличие от object storage, где таблица из тысяч файлов разбивается на тысячи splits, JDBC-источник не партиционируется параллельно «из коробки». Это нормально: реляционные источники чаще используют как dimension-таблицы (относительно небольшие), а не как fact-таблицы на миллиарды строк.
Зато pushdown в RDBMS-коннекторах особенно ценен. У источника есть полноценный SQL-движок — глупо тянуть всю таблицу в Trino, чтобы потом отфильтровать. Хорошие JDBC-коннекторы проталкивают в источник predicate, projection, нередко aggregation, иногда join между таблицами одного источника. Trino фактически переписывает часть запроса в SQL источника и отдаёт ему.
Это видно на EXPLAIN. Когда фильтр протолкнут, в плане у TableScan появляется встроенный предикат, а отдельного Filter-оператора нет:
EXPLAIN SELECT customer_id FROM postgresql.public.orders
WHERE status = 'PAID';
Fragment 0 [SOURCE]
TableScan[table = postgresql:public.orders,
constraint = (status = 'PAID')]
customer_id := customer_id:bigint
Предикат status = 'PAID' ушёл в constraint самого TableScan — значит, фильтрацию выполнит PostgreSQL, и по сети к Trino придут только нужные строки. Без pushdown в плане был бы отдельный Filter, и Trino тянул бы всю таблицу.
Помните про границу параллелизма JDBC-источников. Запрос вида “join большой fact-таблицы из PostgreSQL с чем-то ещё” может упереться в то, что fact-таблица читается одним соединением. Большие fact-данные лучше держать на object storage, а реляционные источники подключать ради dimension-таблиц и федерации.
NoSQL и поисковые движки
Третья категория — нереляционные хранилища: Cassandra, MongoDB, Redis и поисковые движки Elasticsearch, OpenSearch, а также Pinot и Druid. Их объединяет то, что родная модель данных не реляционная, и коннектор делает нетривиальную работу, представляя источник в виде таблиц со столбцами.
Cassandra устроена вокруг partition key и clustering columns — коннектор мапит keyspace на schema, а таблицу на таблицу, но за плоской табличной картинкой стоит специфика: эффективны запросы по ключу партиции, неэффективны полные сканы. MongoDB хранит документы переменной структуры — коннектор должен либо вывести схему по сэмплу документов, либо взять её из явного описания, а вложенные документы превращаются в тип ROW. Elasticsearch и OpenSearch — поисковые индексы; коннектор представляет индекс как таблицу и умеет передавать в движок поиска часть условий.
Общая мерка по нашим трём осям здесь даёт пёструю картину. Параллелизм бывает (Cassandra читается по token range, Elasticsearch по шардам), но pushdown и его семантика сильно зависят от источника, а полноценной статистики для CBO обычно нет.
ClickHouse: колоночная OLAP-база как альтернатива NoSQL для аналитики Поэтому к NoSQL-коннекторам стоит относиться с осторожностью: проверять по документации, какие условия проталкиваются, и не ждать, что оптимизатор построит идеальный план без статистики.
Streaming: Kafka и логи
Четвёртая категория — streaming. Главный представитель — Kafka: коннектор представляет топик как таблицу, где сообщения это строки. Сюда же относится Loki — коннектор к системе логов Grafana Loki.
Семантика streaming-источников особенная. Топик Kafka это не статичная таблица: в него постоянно дописываются сообщения. Чтение топика через Trino это снимок на момент запроса. Splits здесь естественно ложатся на разделы топика — каждый partition читается своей задачей, так что параллелизм определяется числом разделов. Сообщения нужно ещё и десериализовать (JSON, Avro и так далее) — это часть работы коннектора.
Streaming-коннекторы хороши для интерактивных запросов «что сейчас в потоке», для разбора и валидации данных, для разовых выборок. Но Trino — это OLAP-движок для аналитических запросов, а не stream-processing-система: непрерывную обработку потока с состоянием делают специализированные инструменты, а Trino даёт SQL-доступ к содержимому потока в моменте.
Kafka: топики, партиции и офсетыКак выбор категории влияет на запрос
Сведём практический вывод. Когда вы пишете федеративный запрос, который трогает таблицы из разных категорий, движок учитывает их разную природу. Большую fact-таблицу из object storage он прочитает множеством параллельных задач. Маленькую dimension-таблицу из PostgreSQL — одним соединением, протолкнув в PostgreSQL фильтр. Это и есть сила федерации: каждый источник используется по своим сильным сторонам, а Trino соединяет результаты.
Понимание категорий помогает и при диагностике. Если запрос медленный, и в нём участвует JDBC-источник, первое подозрение — fact-таблица читается одним split. Если участвует NoSQL без статистики — оптимизатор мог построить плохой план из-за отсутствия данных о кардинальности. Категория источника — это первая гипотеза при разборе проблемного запроса.
Попробуй сам
Откройте список коннекторов в документации Trino (trino.io/docs/current/connector.html) и составьте свою таблицу-карту:
- Выпишите 8-10 коннекторов и отнесите каждый к одной из четырёх категорий: object storage, RDBMS, NoSQL/search, streaming.
- Для двух коннекторов из категории RDBMS откройте их страницы и найдите раздел про pushdown — сравните, какие виды pushdown поддержаны.
- Для одного коннектора object storage (Iceberg) и одного NoSQL (MongoDB) проверьте, упоминается ли поддержка статистики таблиц.
- Найдите коннектор Lakehouse и сформулируйте, чем он отличается от четырёх отдельных коннекторов Hive / Iceberg / Delta / Hudi.
Эта карта пригодится в модулях про lakehouse и федерацию — там мы будем разбирать конкретные коннекторы вглубь.