Presto
Presto (и его форк Trino) — распределённый SQL-движок для интерактивных запросов по петабайтам данных: быстрые SELECT по HDFS, S3, БД и API одновременно.
1. Что такое Presto
Presto — не хранилище: он «приезжает» к данным через коннекторы. Запрос к нескольким источникам (HDFS + MySQL + Kafka) в одном SELECT — федеративные запросы.
Отличие от Hive (пакетные задачи) — интерактивность: ответы за секунды, а не минуты.
2. Архитектура
- Coordinator — принимает запросы, строит план, раздаёт задачи.
- Workers — исполняют фрагменты запроса, обмениваются данными в памяти.
- Connectors — источники: iceberg, hive, jdbc, kafka, s3.
3. Установка
docker run -d --name trino -p 8080:8080 trinodb/trino
docker exec -it trino trinoКлиенты: trino CLI, JDBC, Python-клиент presto-python-client.
4. Каталоги и схемы
SHOW CATALOGS; # hive, mysql, tpch, system...
SHOW SCHEMAS FROM hive;
USE hive.default;
SELECT count(*) FROM my_table;Каталог соответствует коннектору: catalog.schema.table — полный адрес данных.
5. Коннекторы
Файл etc/catalog/mysql.properties:
connector.name=mysql
connection-url=jdbc:mysql://db-host:3306
connection-user=readonly
connection-password=secretДобавил файл — перезагрузи Coordinator — и БД доступна как каталог.
6. Федеративный запрос
SELECT
u.name,
sum(o.total) AS spent
FROM mysql.shop.users u
JOIN hive.warehouse.orders o ON u.id = o.user_id
WHERE o.dt >= DATE '2026-01-01'
GROUP BY u.name
ORDER BY spent DESC;Один запрос — данные из двух миров.
7. Типичные задачи
- Интерактивное исследование и валидация данных.
- Ad-hoc запросы к ClickHouse, MongoDB, PostgreSQL из одного клиента.
- Панели в Grafana через Presto-коннектор.
8. Производительность
- Данные в колоночных форматах (Parquet/ORC) читаются быстрее в 5–10 раз.
- Presto выполняет вычисления в памяти: профилируй использование памяти workers.
- Для тяжёлого ETL оставь Hive/Spark, Presto — интерактивные SELECT.
9. Экосистема
- Trino — открытый форк Presto, дальнейшее развитие проекта.
- Клиенты: dBeaver, JetBrains DataGrip, superset, Zeppelin.
- Хранение: часто поверх Hive Metastore + S3/ADLS.
10. Партиции и формат хранения
Разбивай данные по датам: партиции ускоряют фильтры, потому что Presto не читает лишние файлы.
SELECT count(*) FROM logs
WHERE dt = DATE '2026-09-01';
-- при партиции dt=... читается один каталог-партиция- колоночные форматы (ORC/Parquet) сильно быстрее текстовых CSV;
- сжимай: snappy/zstd ускоряют чтение и экономят память workers;
- партиционируй по дате и по региону, если подмножества логичны;
- избегай слишком мелких партиций — план раздувается управлением тысячами файлов.
11. Продвинутый SQL: оконные функции
Оконные функции считают значения в рамках группы, не сжимая строки — удобно для рангов и накоплений:
SELECT
user_id,
revenue,
rank() OVER (ORDER BY revenue DESC) AS rnk,
sum(revenue) OVER (PARTITION BY month) AS month_total
FROM sales;Полезные приёмы:
LAG / LEAD— сравнение с предыдущей/следующей строкой;ROW_NUMBER()— дедупликация «последняя запись по ключу»;regexp_extractи каст типов — подготовка текста на лету;- UNNEST — разворачивание массивов в строки.
12. Безопасность и аутентификация
Presto/Trino умеют работать с внешними источниками авторизации:
http-server.authentication.type=DELEGATED # через прокси
http-server.authentication.type=PASSWORD # LDAP / RADIUS
http-server.http.enabled=false # только HTTPS- включай TLS для Coordinator и workers:
https-server.*; - права задаются Connector Access Control;
- для подстановки пользователей используй Impersonation.
13. Экосистема и инструменты
Presto/Trino хорошо встраивается в пайплайны:
- Zeppelin и Jupyter — запросы в ноутбуках;
- dbt — строит модели поверх Trino-коннектора;
- Grafana с Trino-датасорсом рисует дашборды на живых данных;
- Airflow оркестрирует запросы как задачи.
trino://user@coordinator:8443/catalog/schemaДержи коннекторы и версию движка в одном документированном месте, а повторно используемые SQL — в version-контроле как dbt-модели или .sql-файлы.
14. Аппроксимации и работа с огромными данными
На петабайтных выборках точные агрегаты дороги. Presto даёт аппроксимации — чуть менее точные, но в разы быстрее:
approx_distinct(user_id) -- HyperLogLog
approx_percentile(revenue, 0.95) -- квантиль
approx_set(user_id) + merge -- склейка оценок по партициям
TABLE(system.query(user_id)) -- нет: для выборок используй TABLESAMPLE
SELECT * FROM logs TABLESAMPLE BERNOULLI (1); -- 1% строк- скисасные оценки: topk, approx_most_frequent для «топ-N»;
- TABLESAMPLE SYSTEM (n) читает целые страницы, BERNOULLI — случайные строки;
- аппроксимации пригодны для дашбордов и ранних версий метрик.
15. EXPLAIN: читаем план запроса
Медленный запрос начинается с плана. EXPLAIN показывает дерево операторов, EXPLAIN ANALYZE добавляет реальные времена и оценки:
EXPLAIN ANALYZE
SELECT region, sum(revenue)
FROM hive.sales.events
WHERE dt >= DATE '2026-09-01'
GROUP BY region;| Симптом в плане | Действие |
|---|---|
| TableScan читает все партиции | добавь фильтр по партиционной колонке |
| Exchange с большим количеством строк | проверь ключи join/shuffle |
| MemoryExceeded на stage | увеличь память worker или упрости query |
| Partial Aggregation без «final» | распределённая агрегация не сжалась — смотри ключи |
16. Оркестрация запросов и тестирование SQL
Повторяемые SQL превращай в артефакты: модели dbt, задачи Airflow, файлы в git.
- dbt профиль для Trino пишется отдельным адаптером:
dbt-trino; - Airflow вызывает
TrinoOperatorили JDBC-оператор с SQL из файла; - тесты на данных: простые
SELECT count(*)на «дырявых» колонках; - храни ожидаемые «золотые» ответы рядом с запросом для регрессий.
dbt/dbt_project.yml
models/analytics/mrr.sql # select ... from hive...
tests/assert_mrr_positive.sql # assert count(*) > 017. Устранение неполадок: типовые симптомы
Два-три диагностируемых симптома закрывают большинство инцидентов:
| Симптом | Причина | Решение |
|---|---|---|
| Все запросы «замерли» | Coordinator перегружен | проверь JVM, очередь запросов, убери «долгие» SELECT |
| Куски плана падают с OOM | мало памяти worker | query.max-memory-per-node и распределённость shuffle |
| Данные «старые» даже после записи | кеш метаданных партиций | refresh materialized view / invalidate |
| CLI висит без вывода | запрос слишком тяжёлый или тупит источник | limit, EXPLAIN, проверка коннектора |
18. Стратегии JOIN и их влияние на план
Trino выбирает способ соединения автоматически, но понимать его полезно: broadcast join копирует маленькую таблицу на каждый worker, partitioned join перераспределяет данные по ключу:
-- посмотреть выбранную стратегию
EXPLAIN (TYPE DISTRIBUTED)
SELECT * FROM orders o
JOIN customers c ON o.customer_id = c.id;| Стратегия | Условие | Риск |
|---|---|---|
| Broadcast | правая таблица мала | переполнение памяти при большой правой части |
| Partitioned | обе таблицы большие | сетевой shuffle по ключу |
| Cross join | квадратное произведение | обычно ошибка в модели |
- правую таблицу в JOIN ставь меньшей — так оптимизатору проще выбрать broadcast;
- фильтры и предикаты выполняй до соединения — меньше данных уходит в shuffle;
- потерянные строки из-за NULL в ключе JOIN обнаруживаются только тестами на реальных данных.
19. Lakehouse: таблицы Iceberg и Delta
Современные кластера читают не «сырьё файлов», а таблицы с метаданными: Apache Iceberg и Delta Lake дают транзакции и versioning поверх объектного хранилища:
-- создание Iceberg-таблицы через Trino
CREATE TABLE db.events_catalog (
event_date DATE,
user_id BIGINT,
event VARCHAR
) WITH (
format = 'PARQUET',
partitioning = ARRAY['event_date']
);- partitioning по дате + хороший формат — главный рычаг скорости сканирования;
- time travel: читай снимок таблицы на прошлую дату без копии данных;
- Iceberg совместим со Spark и Flink — единая таблица для аналитики и стриминга;
- настрой имена файлов и метаданные в S3 — вложенность каталогов имеет значение для производительности.
20. Память и сброс на диск (spill)
Пока данные помещаются в память worker-а — всё быстро. Когда нет — Trino либо падает с OOM, либо (с включённым спиллом) сбрасывает промежуточные данные на диск:
-- конфиг на воркере: помимо max-memory-per-node
spill-enabled=true
spill-path=/mnt/spool -- быстрый локальный диск- спилл спасает от падения, но сильно замедляет: диск в десятки раз медленнее ОЗУ;
- включай спилл как страховку, а не как способ «тяжёлых» запросов;
- следи за метрикой памяти по ноде и скорректируй query.max-memory-per-node;
- после спилла возрастает время запроса — добавь таймауты и предупреждай пользователей.
21. Мониторинг кластера
Даже оптимизированный запрос не поможет, если кластер перегружен. Собирай сигналы «до» жалоб пользователей:
| Метрика | Что сигнализирует |
|---|---|
| Running Queries | очередь растёт — координатор не справляется |
| Memory usage / node | приближение к лимиту — риск OOM и спилла |
| CPU и IO по ноде | перекос загрузки работников |
| Среднее время запроса | деградация незаметна, но чувствуется |
curl -s localhost:8081/v1/query?max_entries=5
-- посмотреть текущие и прошедшие запросы кластераЧто дальше
Разведай данные в Presto, храни и обрабатывай в Spark/Hive, а метрики из Kafka и ClickHouse подключай коннекторами.