Reference-коннекторы RDBMS: PostgreSQL, MySQL, SQL Server, Oracle
Прошлые два модуля разбирали lakehouse — Trino поверх файлов в object storage. Но Trino создавался не только для этого. Его вторая фундаментальная роль — query federation: способность одним SQL-запросом обращаться к разным источникам данных сразу, в том числе к классическим реляционным базам. Этот модуль посвящён федерации, и начинается он с самого распространённого случая — подключения реляционных СУБД. Урок объясняет, что такое федерация, как Trino подключает PostgreSQL, MySQL, SQL Server и Oracle, и почему эти коннекторы называют reference-коннекторами.
Что такое query federation
Вспомним базовое определение из начала курса: Trino — распределённый SQL-движок, а не база данных. У него нет своего хранилища. Данные живут в подключённых источниках, а Trino исполняет SQL поверх них.
Query federation — это прямое следствие такой архитектуры, доведённое до логического конца. Раз у Trino нет своего хранилища и он умеет читать из разных источников, то ничто не мешает одному запросу читать из нескольких источников одновременно и соединять данные между ними. Запрос может сджойнить таблицу из PostgreSQL с таблицей из MySQL и с Parquet-файлом в S3 — и всё это одним SELECT, без предварительного копирования данных в общее место.
Проблема, которую это решает, в каждой организации одна и та же: данные разбросаны. Транзакционная база приложения — в PostgreSQL. Биллинг — в MySQL. Корпоративная система — в Oracle. Аналитический слой — в lakehouse на S3. Классический ответ — построить ETL-пайплайны, которые копируют всё в одно хранилище, и только там джойнить. Это работает, но это инфраструктура, расписания, задержка между источником и копией, дублирование данных.
Федерация предлагает другой подход: оставить данные там, где они есть, и запрашивать их на месте. Trino становится единой точкой SQL-доступа ко всему ландшафту данных. Не «скопируй, потом запроси», а «запроси там, где лежит».
Каждый источник — это каталог
Механика подключения уже знакома по модулям про lakehouse. Каждый источник данных в Trino — это каталог: отдельный *.properties-файл, задающий коннектор и параметры подключения. Для реляционной базы каталог указывает коннектор СУБД и реквизиты доступа.
# etc/catalog/postgresql.properties — подключение базы PostgreSQL
connector.name=postgresql
connection-url=jdbc:postgresql://pg-host:5432/appdb
connection-user=trino_reader
connection-password=secret
# etc/catalog/mysql.properties — подключение базы MySQL
connector.name=mysql
connection-url=jdbc:mysql://mysql-host:3306
connection-user=trino_reader
connection-password=secret
После добавления каталога его таблицы доступны в трёхуровневой адресации каталог.схема.таблица. Имя каталога — это имя .properties-файла. Можно подключить несколько баз одного типа: два разных PostgreSQL станут двумя каталогами postgresql_main.properties и postgresql_billing.properties — имя файла свободно, важен лишь connector.name внутри.
-- Обычный SELECT из таблицы PostgreSQL через каталог postgresql
SELECT customer_id, name, country
FROM postgresql.public.customers
WHERE country = 'DE'
LIMIT 3;
-- customer_id | name | country
-- -------------+--------------+---------
-- 101 | Müller GmbH | DE
-- 118 | Schäfer KG | DE
-- 204 | Becker AG | DE
А вот федеративный join — две разные базы в одном запросе:
-- Федеративный join: customers из PostgreSQL, payments из MySQL.
-- Данные не копируются — Trino читает обе базы и соединяет результат.
SELECT c.name, sum(p.amount) AS total_paid
FROM postgresql.public.customers c
JOIN mysql.billing.payments p
ON c.customer_id = p.customer_id
WHERE c.country = 'DE'
GROUP BY c.name
ORDER BY total_paid DESC;
-- name | total_paid
-- --------------+------------
-- Becker AG | 48200.00
-- Müller GmbH | 31050.00
-- Schäfer KG | 12700.00
Reference-коннекторы: эталон для всего семейства JDBC
Trino поддерживает много реляционных источников: PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, Redshift, ClickHouse, Snowflake, BigQuery, DuckDB и другие. Внутри Trino все они построены поверх общего фундамента — JDBC, стандартного Java-интерфейса доступа к реляционным базам. Поэтому их называют JDBC-коннекторами (устройству этого общего слоя посвящён следующий урок).
Четыре коннектора в этом семействе — PostgreSQL, MySQL, SQL Server и Oracle — занимают особое место: их называют reference-коннекторами, эталонными. Причина не в том, что они «лучше» остальных, а в их роли внутри проекта Trino.
Это самые зрелые, наиболее полно реализованные и тщательнее всего протестированные коннекторы семейства. Они покрывают самые распространённые в индустрии реляционные базы, поэтому на них приходится основная нагрузка реального использования. И главное — они служат образцом: новые JDBC-коннекторы пишутся, ориентируясь на них; то, как reference-коннектор решает маппинг типов, метаданные, pushdown, становится моделью для остальных. Если функциональность есть в reference-коннекторе — велик шанс, что она дойдёт и до прочих JDBC-коннекторов.
Практический вывод для дата-инженера: когда вы изучили работу с PostgreSQL-коннектором — маппинг типов, pushdown, метаданные, — вы фактически изучили общую модель всего JDBC-семейства. Различия между конкретными JDBC-коннекторами есть, но они вторичны на фоне общего каркаса.
Стоит отметить и то, что не все «реляционные» коннекторы Trino одинаковы по своей природе. Часть источников — например, BigQuery или Snowflake — это облачные аналитические хранилища со своими нативными протоколами и собственной моделью масштабирования; их коннекторы устроены сложнее классического JDBC-обёртывания, хотя для пользователя адресация каталог.схема.таблица выглядит так же. Reference-коннекторы же — это именно «честные» JDBC-коннекторы поверх традиционных СУБД, и потому они и стали эталоном: на них проще всего изучить и каркас, и его ограничения, не отвлекаясь на облачную специфику. Когда в курсе или документации говорят «JDBC-коннектор», по умолчанию подразумевают модель, заданную reference-коннекторами.
Ещё одно наблюдение про роль reference-коннекторов в развитии Trino. Новые виды pushdown, улучшения маппинга типов, оптимизации обычно сначала появляются и обкатываются в reference-коннекторах, а затем распространяются на остальные. Поэтому, если вы видите в документации, что некоторая возможность поддержана PostgreSQL-коннектором, но не указана для менее ходового JDBC-коннектора, — это часто не «никогда не будет», а «пока не дошло». Reference-коннекторы задают передний край того, что вообще умеет JDBC-семейство Trino.
Документация Trino описывает каждый коннектор отдельной страницей, но reference-коннекторы документированы наиболее полно: маппинг типов в обе стороны, поддерживаемые виды pushdown, особенности. Если работаете с менее ходовым JDBC-коннектором и его страница лаконична — смотрите страницу PostgreSQL: общая механика там та же, отличаются детали.
Trino поверх реляционной базы — это OLAP, а не замена базы
Важное предостережение, прямо вытекающее из природы Trino. Подключив PostgreSQL к Trino, легко поддаться иллюзии, что Trino теперь «работает как PostgreSQL». Это не так, и понимать разницу критично.
Trino — OLAP-движок: он предназначен для аналитических запросов, сканирующих и агрегирующих большие объёмы. Он не предназначен для OLTP — точечных операций, на которых живёт транзакционная база: «вставь одну строку», «обнови баланс по id», «прочитай одну запись по первичному ключу». У Trino нет транзакций уровня БД, нет индексов в традиционном понимании, нет смысла гонять через него точечные операции.
Поэтому правильная роль Trino поверх реляционной базы — аналитика над её данными: отчёты, агрегации, и особенно — федеративные join, соединяющие данные этой базы с другими источниками. Точечные транзакционные операции остаются приложению, которое работает с базой напрямую. Trino не заменяет PostgreSQL — он добавляет над ним (и над всеми другими источниками) аналитический федеративный слой.
Есть и эксплуатационное следствие. Аналитический запрос Trino к таблице PostgreSQL может прочитать из неё значительный объём данных и создать на боевую транзакционную базу заметную нагрузку. Поэтому на практике Trino-каталог часто направляют не на саму боевую базу под нагрузкой пользователей, а на её read-реплику. Тонкости того, что именно Trino вычитывает из источника, разбираются в уроке про pushdown.
Подключение реляционной базы к Trino не делает Trino её заменой. Trino поверх PostgreSQL — это OLAP-слой для аналитики и федерации, а не OLTP-движок. Точечные вставки и обновления по id через Trino гонять не нужно — для этого есть сама база. Помните о нагрузке: тяжёлый аналитический запрос Trino способен ощутимо нагрузить боевую транзакционную базу, поэтому каталог разумно направлять на read-реплику.
Попробуй сам
В песочнице курса поднимите два реляционных источника — например, контейнер PostgreSQL и контейнер MySQL — и наполните каждый небольшими таблицами (в PostgreSQL — customers, в MySQL — payments, связанные по customer_id). Упражнение первое: создайте в Trino два каталога, по одному .properties-файлу на базу, и проверьте подключение командой SHOW SCHEMAS FROM postgresql и SHOW TABLES FROM postgresql.public. Упражнение второе: выполните обычный SELECT из таблицы PostgreSQL, затем обычный SELECT из таблицы MySQL — убедитесь, что каждый каталог виден независимо. Упражнение третье, ключевое: напишите один федеративный SELECT с JOIN между таблицей PostgreSQL и таблицей MySQL по customer_id с агрегацией. Письменно ответьте на два вопроса: какую инфраструктурную работу (по сравнению с классическим ETL) вам не пришлось делать, чтобы выполнить этот join, и почему отправлять через Trino точечную вставку одной строки в PostgreSQL — плохая идея.