Trino (originally PrestoSQL) and Presto (PrestoDB) are distributed SQL query engines designed to run interactive analytical queries over heterogeneous data sources. Both descend from the engine Facebook built in 2012 to query Hadoop with low latency; the project forked in 2020 when the original creators left Facebook and renamed their fork Trino. Today Trino is the more actively developed branch and the de-facto open query engine for the lakehouse.
The sections below describe the coordinator and worker architecture, how a SQL statement becomes distributed tasks, a configuration and federated-query example, and how Trino compares with other engines.
A Trino cluster has one coordinator and many workers. The coordinator accepts SQL over HTTP, parses and analyses it against catalog metadata, builds and optimises a plan, and schedules work. Workers execute tasks and exchange intermediate data with each other over the network. Each catalog in Trino is an instance of a connector: the connector tells the planner what tables and statistics exist, which filters and projections it can push down, and how to split the data into independently readable units. Trino stores no table data of its own, which is why it is described as a query engine rather than a database.
The optimiser rewrites the plan using table statistics, reorders joins, chooses broadcast or partitioned joins, and pushes filters into connectors. The plan is cut into fragments at exchange boundaries; each fragment becomes a stage made of tasks on many workers. Leaf stages read splits, such as Parquet files or row groups for Iceberg, in parallel. Operators process data in pages of columnar values and stream them to the next stage, so results can start returning before the whole input is read. The classic trade-off is that a long query fails as a whole if a worker dies; fault-tolerant execution mode spools intermediate data to storage and retries tasks, at some cost in latency, which suits long batch jobs.
# etc/catalog/lake.properties
connector.name=iceberg
iceberg.catalog.type=rest
iceberg.rest-catalog.uri=http://polaris:8181/api/catalog
# etc/catalog/crm.properties
connector.name=postgresql
connection-url=jdbc:postgresql://crm-db:5432/crm
connection-user=trino
connection-password=${ENV:CRM_PASSWORD}
-- join a lakehouse fact table with an operational Postgres table
SELECT c.segment, date_trunc('month', o.order_ts) AS month, sum(o.amount) AS revenue
FROM lake.sales.orders o
JOIN crm.public.customers c ON c.id = o.customer_id
WHERE o.order_ts >= DATE '2026-01-01'
GROUP BY 1, 2
ORDER BY 2, 1;
EXPLAIN ANALYZE SELECT count(*) FROM lake.sales.orders WHERE region = 'EMEA';
The date filter is pushed into the Iceberg connector for partition and file pruning; the Postgres side is read through JDBC. EXPLAIN ANALYZE shows per-stage rows, CPU time and how much data each scan actually read, which is the first tool for diagnosing a slow query.
| Engine | Best at | Consider instead when |
|---|---|---|
| Trino / Presto | Interactive SQL over many sources, lakehouse BI | — |
| Spark | Large ETL, ML pipelines, Python/Scala code | Jobs run for hours or need custom code |
| StarRocks / Doris | Low-latency dashboards with local storage and caching | Sub-second, high-concurrency serving |
| DuckDB | Single-node analytics | Data fits on one machine |
query.max-memory-per-node; enable spilling or fault-tolerant execution for heavy queries.ANALYZE on lakehouse tables.See Open Table Formats for the tables Trino reads and Catalogs for how they are registered.