π§ Fundamentals
π― What is Presto/Trino?
Presto (now Trino) is a distributed SQL query engine designed for fast analytics on large datasets. It queries data where it lives β HDFS, S3, Kafka, relational databases, and more β without moving it. It's the "SQL-on-everything" engine.
Why Presto/Trino Matters
Speed: Interactive queries. Federation: Query anywhere. Scale: Petabytes. SQL: ANSI SQL. Open: Apache/Trino. No ETL: Query in place.
# Presto/Trino β the big picture
# Distributed SQL query engine for analytics.
# CONCEPTUAL OVERVIEW
print("""
=== Presto/Trino ===
What it is:
- Distributed SQL query engine
- Fast analytics
- Queries data in place
- No data movement
- Federated queries
Key features:
- ANSI SQL
- Connectors (Hive, S3, Kafka, etc.)
- In-memory processing
- MPP architecture
- Petabyte scale
What it's NOT:
- Not a database
- Not a storage system
- Not for OLTP
- Not for writes (mostly)
""")
# SIMPLE QUERY EXAMPLE
print("=== Simple Query Example ===")
print("""
-- Query S3 data directly
SELECT
date,
COUNT(*) as events,
COUNT(DISTINCT user_id) as users
FROM s3.logs.events
WHERE date >= DATE '2024-01-01'
GROUP BY date
ORDER BY date;
-- Federated query (join across systems)
SELECT
u.name,
o.order_id,
o.amount
FROM postgres.public.users u
JOIN hive.analytics.orders o
ON u.id = o.user_id
WHERE o.date >= DATE '2024-01-01';
""")
# KEY PROPERTIES
print("""
=== Key Properties ===
1. DISTRIBUTED SQL
- MPP architecture
- Parallel execution
- Petabyte scale
2. FEDERATION
- Query multiple sources
- Single SQL query
- No data movement
3. IN-MEMORY
- Processing in memory
- No disk shuffle
- Fast
4. ANSI SQL
- Standard SQL
- Rich functions
- Window functions
5. CONNECTORS
- Hive
- S3
- Kafka
- PostgreSQL
- MySQL
- Cassandra
- Elasticsearch
- Many more
6. SEPARATION
- Compute and storage
- Scale independently
""")
# REAL-WORLD SCALE
print("=== Real-World Deployments ===")
deployments = [
('Facebook', 'Original creator', 'Petabytes, interactive'),
('Netflix', 'Trino', 'Data warehouse'),
('Uber', 'Presto', 'Analytics'),
('Airbnb', 'Trino', 'Data lake'),
('Lyft', 'Presto', 'Analytics'),
('Starburst', 'Trino', 'Enterprise'),
]
print(f"{'Company':<15} {'Engine':<15} {'Use Case':<30}")
print("-" * 60)
for company, engine, use_case in deployments:
print(f"{company:<15} {engine:<15} {use_case:<30}")π Presto to Trino
π― The Fork Story
Presto was created at Facebook in 2012. In 2019, the original creators forked it to create Trino after disagreements about governance. Today, Trino is the active community version, while Presto remains with Facebook (PrestoDB) and PrestoSQL became Trino.
History
2012: Presto at Facebook. 2013: Open source. 2019: Trino fork. 2020: Trino renamed. Now: Two projects. Trino: Active community.
# Presto to Trino β the fork story
print("=== Timeline ===")
print("""
2012: Presto created at Facebook
- By Martin Traverso, Dain Sundstrom,
David Phillips, Eric Hwang
- For interactive analytics on Hive
2013: Presto open sourced
- Apache license
- Presto Software Foundation (2019)
2019: Trino fork
- Original creators left Facebook
- Created PrestoSQL
- Renamed to Trino (2020)
2020: Trino renamed
- PrestoSQL β Trino
- Community-driven
- Active development
Now: Two projects
- PrestoDB (Facebook)
- Trino (community)
""")
print("\n=== PrestoDB vs Trino ===")
print(f"{'Aspect':<25} {'PrestoDB':<25} {'Trino':<25}")
print("-" * 75)
print(f"{'Governance':<25} {'Presto Foundation':<25} {'Trino Foundation':<25}")
print(f"{'Creator':<25} {'Facebook':<25} {'Original team':<25}")
print(f"{'Community':<25} {'Smaller':<25} {'Larger':<25}")
print(f"{'Development':<25} {'Active':<25} {'Very active':<25}")
print(f"{'Features':<25} {'Stable':<25} {'Cutting-edge':<25}")
print(f"{'Adoption':<25} {'Enterprise':<25} {'Broad':<25}")
print(f"{'Connectors':<25} {'Many':<25} {'Many + more':<25}")
print("\n=== Naming ===")
print("""
PrestoDB:
- Official name: Presto
- Maintained by: Presto Software Foundation
- Backed by: Facebook (Meta)
- GitHub: prestodb/presto
Trino:
- Official name: Trino
- Maintained by: Trino Software Foundation
- Created by: Original Presto team
- GitHub: trinodb/trino
Note: "Presto" often refers to both.
Trino is the modern community version.
""")
print("\n=== Why It Matters ===")
print("""
For users:
- Trino is the active community
- More features
- More connectors
- Better performance
For enterprises:
- Both are supported
- Starburst (Trino)
- Ahana (Presto)
- Choose based on needs
Migration:
- Trino is mostly compatible
- Presto β Trino migration path
- SQL compatible
""")ποΈ Architecture
π― MPP Architecture
Trino uses a coordinator-worker architecture. The coordinator parses queries, creates plans, and schedules tasks. Workers execute tasks in parallel. This is MPP (Massively Parallel Processing).
Architecture
Coordinator: Query planning. Workers: Execution. Discovery: Service registry. Connectors: Data sources. Split: Unit of work. Stage: Query phase.
# Trino Architecture
print("=== Architecture Diagram ===")
print("""
βββββββββββββββββββββββββββββββββββββββββββ
β Client β
β (CLI, JDBC, ODBC) β
βββββββββββββββββββ¬ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββ
β Coordinator β
β β
β - Parse SQL β
β - Analyze β
β - Plan β
β - Optimize β
β - Schedule β
β - Manage workers β
βββββββββββββββββββ¬ββββββββββββββββββββββββ
β
βββββββββββββΌββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββ βββββββββββ βββββββββββ
βWorker 1 β βWorker 2 β βWorker 3 β
β β β β β β
β- Executeβ β- Executeβ β- Executeβ
β- Processβ β- Processβ β- Processβ
β- Exchangeβ β- Exchangeβ β- Exchangeβ
ββββββ¬βββββ ββββββ¬βββββ ββββββ¬βββββ
β β β
βββββββββββββΌββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββ
β Connectors β
β β
β Hive β S3 β Kafka β PostgreSQL β ... β
βββββββββββββββββββββββββββββββββββββββββββ
""")
print("\n=== Components ===")
print("""
1. COORDINATOR
- Entry point
- Parses SQL
- Creates plan
- Schedules tasks
- Manages workers
- Single node (or HA)
2. WORKER
- Executes tasks
- Processes data
- Exchanges data
- Multiple nodes
- Scales horizontally
3. DISCOVERY SERVICE
- Service registry
- Workers register
- Coordinator discovers
- Embedded or external
4. CONNECTOR
- Interface to data source
- Hive, S3, Kafka, etc.
- Split generation
- Page source
5. SPLIT
- Unit of work
- Part of a table
- Processed by worker
6. STAGE
- Query phase
- Tree of stages
- Exchange between stages
""")
print("\n=== Query Execution ===")
print("""
1. PARSE
- SQL β AST
- Syntax check
2. ANALYZE
- Semantic analysis
- Resolve tables, columns
3. PLAN
- Logical plan
- Optimize
4. SCHEDULE
- Physical plan
- Split into stages
- Assign to workers
5. EXECUTE
- Workers process
- Exchange data
- Pipeline execution
6. RETURN
- Results to coordinator
- Stream to client
""")
# IMPLEMENTATION
print("\n=== Simulating Trino Architecture ===")
import time
import random
from collections import defaultdict
class TrinoCoordinator:
"""Simulate Trino Coordinator."""
def __init__(self):
self.workers = {}
self.queries = []
def register_worker(self, worker_id, capacity=4):
"""Register worker."""
self.workers[worker_id] = {
'id': worker_id,
'capacity': capacity,
'active_tasks': 0,
}
print(f"Coordinator: Registered worker {worker_id}")
def submit_query(self, sql):
"""Submit query."""
print(f"\nCoordinator: Received query")
print(f" SQL: {sql[:60]}...")
# Parse (simplified)
query = {
'id': f"query_{len(self.queries)}",
'sql': sql,
'state': 'planning',
'splits': [],
'tasks': [],
}
# Plan: create splits
num_splits = random.randint(4, 10)
query['splits'] = [f"split_{i}" for i in range(num_splits)]
print(f" Created {num_splits} splits")
# Schedule: assign to workers
for split in query['splits']:
# Find worker with capacity
worker = self._find_worker()
if worker:
task = {
'id': f"task_{split}",
'split': split,
'worker': worker['id'],
'state': 'running',
}
worker['active_tasks'] += 1
query['tasks'].append(task)
print(f" Scheduled {len(query['tasks'])} tasks")
# Execute
query['state'] = 'running'
self.queries.append(query)
# Simulate execution
time.sleep(0.5)
# Complete
query['state'] = 'finished'
for task in query['tasks']:
if task['worker'] in self.workers:
self.workers[task['worker']]['active_tasks'] -= 1
task['state'] = 'success'
print(f" Query completed")
return query
def _find_worker(self):
"""Find worker with capacity."""
for worker in self.workers.values():
if worker['active_tasks'] < worker['capacity']:
return worker
return None
def get_status(self):
return {
'workers': len(self.workers),
'queries': len(self.queries),
'completed': len([q for q in self.queries if q['state'] == 'finished']),
}
# Demo
print("=== Trino Architecture Simulation ===")
coordinator = TrinoCoordinator()
# Register workers
for i in range(1, 4):
coordinator.register_worker(f"worker_{i}", capacity=4)
# Submit queries
queries = [
"SELECT COUNT(*) FROM hive.analytics.events",
"SELECT user_id, SUM(amount) FROM postgres.orders GROUP BY user_id",
"SELECT * FROM s3.logs WHERE date = '2024-01-01'",
]
for sql in queries:
result = coordinator.submit_query(sql)
print(f" Result: {result['state']}")
# Status
print(f"\nCoordinator status: {coordinator.get_status()}")
# ARCHITECTURE SUMMARY
print("\n=== Architecture Summary ===")
print(f"{'Component':<25} {'Role':<40}")
print("-" * 65)
print(f"{'Coordinator':<25} {'Query planning':<40}")
print(f"{'Worker':<25} {'Execution':<40}")
print(f"{'Discovery':<25} {'Service registry':<40}")
print(f"{'Connector':<25} {'Data source interface':<40}")
print(f"{'Split':<25} {'Unit of work':<40}")
print(f"{'Stage':<25} {'Query phase':<40}")π Connectors
π― Query Any Data Source
Connectors let Trino query different data sources. Trino has connectors for Hive, S3, Kafka, relational databases, NoSQL, and more. You can join data across connectors in a single query.
Connectors
Hive: HDFS/S3. S3: Object store. Kafka: Streaming. JDBC: Databases. Cassandra: NoSQL. Federation: Join across.
# Trino Connectors
print("=== What is a Connector? ===")
print("""
Connector:
- Interface to data source
- Maps data to SQL tables
- Generates splits
- Handles reads/writes
Types:
- Storage: Hive, S3, Iceberg, Delta
- Streaming: Kafka, Kinesis
- Databases: PostgreSQL, MySQL, Oracle
- NoSQL: Cassandra, MongoDB, Redis
- Search: Elasticsearch
- Other: JMX, Memory, TPCH
""")
print("\n=== Common Connectors ===")
print("""
1. HIVE
- HDFS, S3
- Parquet, ORC, Avro
- Partitioned tables
CREATE TABLE hive.analytics.events (...)
WITH (format = 'PARQUET', partitioned_by = ARRAY['date']);
2. ICEBERG
- ACID tables
- Time travel
- Schema evolution
CREATE TABLE iceberg.analytics.events (...);
3. DELTA LAKE
- ACID tables
- Databricks
CREATE TABLE delta.analytics.events (...);
4. KAFKA
- Streaming data
- Real-time queries
SELECT * FROM kafka.events LIMIT 10;
5. POSTGRESQL
- Relational data
- Federation
SELECT * FROM postgres.public.users;
6. CASSANDRA
- NoSQL
- Wide-column
SELECT * FROM cassandra.analytics.users;
""")
print("\n=== Federated Query ===")
print("""
-- Join across connectors
SELECT
u.name,
o.order_id,
o.amount
FROM postgres.public.users u
JOIN hive.analytics.orders o
ON u.id = o.user_id
WHERE o.date >= DATE '2024-01-01';
-- Trino fetches from both sources
-- Joins in memory
-- Returns combined results
""")
print("\n=== Catalog Configuration ===")
print("""
# etc/catalog/hive.properties
connector.name=hive
hive.metastore.uri=thrift://metastore:9083
hive.s3.endpoint=s3.amazonaws.com
# etc/catalog/postgres.properties
connector.name=postgresql
connection-url=jdbc:postgresql://localhost:5432/mydb
connection-user=user
connection-password=pass
# etc/catalog/kafka.properties
connector.name=kafka
kafka.nodes=localhost:9092
kafka.table-names=events
""")
# IMPLEMENTATION
print("\n=== Simulating Connectors ===")
class Connector:
"""Base connector."""
def __init__(self, name, catalog):
self.name = name
self.catalog = catalog
self.tables = {}
def get_splits(self, table):
"""Get splits for table."""
return [f"{table}_split_{i}" for i in range(3)]
def read(self, table, split):
"""Read data."""
return [{'id': i, 'value': f"{table}_{i}"} for i in range(10)]
class HiveConnector(Connector):
def __init__(self):
super().__init__('hive', 'hive')
class PostgresConnector(Connector):
def __init__(self):
super().__init__('postgresql', 'postgres')
class KafkaConnector(Connector):
def __init__(self):
super().__init__('kafka', 'kafka')
class TrinoEngine:
"""Simulate Trino engine."""
def __init__(self):
self.connectors = {}
def register_connector(self, connector):
"""Register connector."""
self.connectors[connector.catalog] = connector
print(f"Trino: Registered connector '{connector.name}' as '{connector.catalog}'")
def query(self, sql):
"""Execute query."""
print(f"\nTrino: Executing query")
print(f" SQL: {sql[:60]}...")
# Parse catalog
for catalog, connector in self.connectors.items():
if catalog in sql.lower():
print(f" Using connector: {connector.name}")
splits = connector.get_splits('table')
print(f" Splits: {len(splits)}")
return {'catalog': catalog, 'splits': splits}
return None
# Demo
print("=== Connector Demo ===")
engine = TrinoEngine()
# Register connectors
engine.register_connector(HiveConnector())
engine.register_connector(PostgresConnector())
engine.register_connector(KafkaConnector())
# Execute queries
queries = [
"SELECT * FROM hive.analytics.events",
"SELECT * FROM postgres.public.users",
"SELECT * FROM kafka.events LIMIT 10",
]
for sql in queries:
result = engine.query(sql)
print(f" Result: {result}")
# CONNECTOR SUMMARY
print("\n=== Connector Summary ===")
print(f"{'Connector':<20} {'Data Source':<30}")
print("-" * 55)
print(f"{'Hive':<20} {'HDFS, S3':<30}")
print(f"{'Iceberg':<20} {'ACID tables':<30}")
print(f"{'Delta':<20} {'Databricks':<30}")
print(f"{'Kafka':<20} {'Streaming':<30}")
print(f"{'PostgreSQL':<20} {'Relational':<30}")
print(f"{'Cassandra':<20} {'NoSQL':<30}")
print(f"{'Elasticsearch':<20} {'Search':<30}")βοΈ Query Engine
π― How Queries Execute
Trino's query engine parses SQL, creates a logical plan, optimizes it, creates a physical plan, and executes it in parallel across workers. The engine is designed for interactive analytics.
Query Engine
Parser: SQL β AST. Analyzer: Semantic. Optimizer: Cost-based. Planner: Physical. Scheduler: Tasks. Execution: Parallel.
# Query Engine
print("=== Query Lifecycle ===")
print("""
1. PARSE
- SQL β AST
- Syntax check
- No semantic check
2. ANALYZE
- Semantic analysis
- Resolve tables, columns
- Type checking
- Catalog access
3. LOGICAL PLAN
- Create logical plan
- Tree of operations
- No execution details
4. OPTIMIZE
- Rule-based
- Cost-based
- Pushdown
- Reorder joins
5. PHYSICAL PLAN
- Create physical plan
- Execution details
- Split assignments
6. SCHEDULE
- Split into stages
- Assign to workers
- Create tasks
7. EXECUTE
- Workers process
- Exchange data
- Pipeline execution
8. RETURN
- Results streamed
- To coordinator
- To client
""")
print("\n=== Optimizations ===")
print("""
1. PREDICATE PUSHDOWN
- Push filter to connector
- Skip data
- Less I/O
2. PARTITION PRUNING
- Skip partitions
- Use metadata
3. JOIN REORDERING
- Cost-based
- Smallest first
4. BROADCAST JOIN
- Small table broadcast
- Avoid shuffle
5. PARTITIONED JOIN
- Large tables
- Shuffle by key
6. COLUMN PRUNING
- Read only needed columns
- Less I/O
7. TOP-N
- Push LIMIT
- Early termination
""")
print("\n=== Execution Model ===")
print("""
Pipeline:
- Tasks stream data
- No blocking
- Low latency
Stages:
- Tree of stages
- Exchange between
- Parallel execution
Splits:
- Unit of work
- Processed by workers
- Many per query
Exchange:
- Data between stages
- In-memory
- Network shuffle
""")
print("\n=== Example Plan ===")
print("""
EXPLAIN SELECT city, COUNT(*)
FROM users
WHERE age > 30
GROUP BY city;
-- Output:
Fragment 0 [SINGLE]
Output[city, count]
ββ Aggregate[city] [count]
ββ RemoteSource[1]
Fragment 1 [HASH]
Aggregate[city] [count]
ββ RemoteSource[2]
Fragment 2 [SOURCE]
ScanFilterProject[table = users, filterPredicate = age > 30]
""")
# IMPLEMENTATION
print("\n=== Simulating Query Engine ===")
class QueryEngine:
"""Simulate Trino query engine."""
def __init__(self):
self.steps = []
def parse(self, sql):
"""Parse SQL."""
self.steps.append('parse')
print(f" Parse: {sql[:50]}...")
return {'sql': sql, 'ast': 'parsed'}
def analyze(self, parsed):
"""Analyze."""
self.steps.append('analyze')
print(f" Analyze: Resolved tables and columns")
return {**parsed, 'analyzed': True}
def logical_plan(self, analyzed):
"""Create logical plan."""
self.steps.append('logical_plan')
print(f" Logical plan: Created")
return {**analyzed, 'logical_plan': 'plan'}
def optimize(self, plan):
"""Optimize."""
self.steps.append('optimize')
print(f" Optimize: Applied rules")
return {**plan, 'optimized': True}
def physical_plan(self, plan):
"""Create physical plan."""
self.steps.append('physical_plan')
print(f" Physical plan: Created")
return {**plan, 'physical_plan': 'execution_plan'}
def execute(self, plan):
"""Execute."""
self.steps.append('execute')
print(f" Execute: Running on workers")
return {'state': 'finished', 'rows': 100}
def run(self, sql):
"""Run query end-to-end."""
print(f"\nQuery: {sql}")
parsed = self.parse(sql)
analyzed = self.analyze(parsed)
logical = self.logical_plan(analyzed)
optimized = self.optimize(logical)
physical = self.physical_plan(optimized)
result = self.execute(physical)
return result
# Demo
print("=== Query Engine Demo ===")
engine = QueryEngine()
sql = "SELECT city, COUNT(*) FROM users WHERE age > 30 GROUP BY city"
result = engine.run(sql)
print(f"\nSteps: {engine.steps}")
print(f"Result: {result}")
# QUERY ENGINE SUMMARY
print("\n=== Query Engine Summary ===")
print(f"{'Phase':<25} {'Description':<40}")
print("-" * 65)
print(f"{'Parse':<25} {'SQL to AST':<40}")
print(f"{'Analyze':<25} {'Semantic analysis':<40}")
print(f"{'Logical plan':<25} {'Tree of operations':<40}")
print(f"{'Optimize':<25} {'Rule + cost-based':<40}")
print(f"{'Physical plan':<25} {'Execution details':<40}")
print(f"{'Execute':<25} {'Parallel on workers':<40}")π SQL Support
π― ANSI SQL
Trino supports ANSI SQL with rich extensions: window functions, complex types, JSON, and more. It's designed to be familiar to anyone who knows SQL.
SQL Support
ANSI SQL: Standard. Window: Functions. Complex: Arrays, maps. JSON: Native. Extensions: Trino-specific. Familiar: SQL developers.
# SQL Support
print("=== ANSI SQL ===")
print("""
Standard SQL:
- SELECT, FROM, WHERE
- GROUP BY, HAVING
- ORDER BY, LIMIT
- JOIN (INNER, LEFT, RIGHT, FULL)
- UNION, INTERSECT, EXCEPT
- Subqueries
- CTEs (WITH)
""")
print("\n=== Window Functions ===")
print("""
SELECT
user_id,
order_date,
amount,
SUM(amount) OVER (
PARTITION BY user_id
ORDER BY order_date
) as running_total,
ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY amount DESC
) as rank
FROM orders;
""")
print("\n=== Complex Types ===")
print("""
-- Arrays
SELECT
tags,
tags[1] as first_tag,
cardinality(tags) as num_tags
FROM posts;
-- Maps
SELECT
attributes,
attributes['color'] as color
FROM products;
-- Rows
SELECT
address.city,
address.zip
FROM users;
-- UNNEST
SELECT
user_id,
tag
FROM users
CROSS JOIN UNNEST(tags) AS t(tag);
""")
print("\n=== JSON Support ===")
print("""
SELECT
json_extract(data, '$.name') as name,
json_extract_scalar(data, '$.age') as age,
json_array_length(json_extract(data, '$.items')) as num_items
FROM events;
-- JSON functions:
-- json_extract, json_extract_scalar
-- json_array_length, json_array_get
-- json_format, json_parse
-- json_size, json_keys
""")
print("\n=== Trino Extensions ===")
print("""
-- LATERAL
SELECT * FROM users
CROSS JOIN LATERAL (
SELECT * FROM orders WHERE user_id = users.id
) o;
-- TABLESAMPLE
SELECT * FROM users TABLESAMPLE BERNOULLI (10);
-- APPROXIMATE
SELECT approx_distinct(user_id) FROM events;
-- DATE/TIME
SELECT
date_trunc('day', timestamp) as day,
date_add('day', 7, date '2024-01-01') as next_week;
""")
print("\n=== Example Queries ===")
print("""
-- Top N per group
SELECT * FROM (
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY category
ORDER BY sales DESC
) as rn
FROM products
) WHERE rn <= 3;
-- Pivot
SELECT * FROM (
SELECT date, category, amount FROM sales
)
PIVOT (
SUM(amount) FOR category IN ('A', 'B', 'C')
);
-- Recursive CTE
WITH RECURSIVE nums(n) AS (
SELECT 1
UNION ALL
SELECT n + 1 FROM nums WHERE n < 10
)
SELECT * FROM nums;
""")
# SQL SUMMARY
print("\n=== SQL Summary ===")
print(f"{'Feature':<25} {'Support':<40}")
print("-" * 65)
print(f"{'SELECT':<25} {'Full':<40}")
print(f"{'JOIN':<25} {'All types':<40}")
print(f"{'GROUP BY':<25} {'Full':<40}")
print(f"{'Window functions':<25} {'Full':<40}")
print(f"{'CTEs':<25} {'Yes':<40}")
print(f"{'Complex types':<25} {'Arrays, maps, rows':<40}")
print(f"{'JSON':<25} {'Native':<40}")
print(f"{'UNNEST':<25} {'Yes':<40}")π Federation
π― Query Across Sources
Federation lets you query data from multiple sources in a single SQL query. Join a PostgreSQL table with an S3 file, or a Kafka stream with Hive data β all without moving data.
Federation
Multiple sources: One query. No ETL: Query in place. Joins: Cross-catalog. Real-time: Fresh data. Simplified: One SQL. Powerful: Combine everything.
# Federation
print("=== What is Federation? ===")
print("""
Federation:
- Query multiple sources
- Single SQL query
- No data movement
- Join across systems
Sources:
- Hive (HDFS, S3)
- PostgreSQL
- MySQL
- Kafka
- Cassandra
- Elasticsearch
- MongoDB
- Redis
""")
print("\n=== Federated Query Example ===")
print("""
-- Join PostgreSQL and Hive
SELECT
u.name,
u.email,
o.order_id,
o.amount,
o.date
FROM postgres.public.users u
JOIN hive.analytics.orders o
ON u.id = o.user_id
WHERE o.date >= DATE '2024-01-01'
ORDER BY o.date DESC;
-- Trino:
-- 1. Reads users from PostgreSQL
-- 2. Reads orders from Hive
-- 3. Joins in memory
-- 4. Returns results
-- No ETL, no data movement!
""")
print("\n=== More Federation Examples ===")
print("""
-- Kafka + Hive
SELECT
k.event_type,
k.user_id,
h.user_name
FROM kafka.events k
JOIN hive.users h ON k.user_id = h.id
WHERE k.timestamp > NOW() - INTERVAL '1' HOUR;
-- PostgreSQL + S3
SELECT
p.product_name,
s.sales_count
FROM postgres.products p
JOIN s3.analytics.sales s ON p.id = s.product_id;
-- Cassandra + MySQL
SELECT
c.user_id,
c.activity,
m.profile
FROM cassandra.analytics.activities c
JOIN mysql.users.profiles m ON c.user_id = m.id;
""")
print("\n=== Benefits ===")
print("""
1. NO ETL
- Query in place
- No data movement
- Always fresh
2. SIMPLIFIED
- One SQL query
- No pipelines
- Less code
3. POWERFUL
- Combine any sources
- Real-time + historical
4. COST-EFFECTIVE
- No data duplication
- Use existing storage
5. FAST
- Parallel reads
- In-memory joins
""")
print("\n=== Limitations ===")
print("""
1. PERFORMANCE
- Cross-network joins
- Can be slow
2. PUSHDOWN
- Not all operations push down
- Some data moves
3. CONSISTENCY
- Different isolation levels
- Not transactional across sources
4. SCHEMA
- Different schemas
- Mapping challenges
""")
# IMPLEMENTATION
print("\n=== Simulating Federation ===")
class FederatedQuery:
"""Simulate federated query."""
def __init__(self):
self.sources = {}
def register_source(self, catalog, data):
"""Register data source."""
self.sources[catalog] = data
print(f"Federation: Registered '{catalog}' with {len(data)} rows")
def query(self, sql):
"""Execute federated query."""
print(f"\nFederated query: {sql[:60]}...")
# Simplified: parse source from SQL
results = []
for catalog, data in self.sources.items():
if catalog in sql.lower():
print(f" Reading from: {catalog}")
results.extend(data)
# Simulate join
return results
# Demo
print("=== Federation Demo ===")
fed = FederatedQuery()
# Register sources
fed.register_source('postgres', [
{'id': 1, 'name': 'Alice', 'email': 'alice@example.com'},
{'id': 2, 'name': 'Bob', 'email': 'bob@example.com'},
])
fed.register_source('hive', [
{'order_id': 101, 'user_id': 1, 'amount': 100},
{'order_id': 102, 'user_id': 2, 'amount': 200},
])
fed.register_source('kafka', [
{'event_id': 1, 'user_id': 1, 'event_type': 'click'},
])
# Execute federated query
sql = """
SELECT u.name, o.order_id, o.amount
FROM postgres.users u
JOIN hive.orders o ON u.id = o.user_id
"""
results = fed.query(sql)
print(f" Results: {len(results)} rows")
# FEDERATION SUMMARY
print("\n=== Federation Summary ===")
print(f"{'Aspect':<25} {'Description':<40}")
print("-" * 65)
print(f"{'Multiple sources':<25} {'One query':<40}")
print(f"{'No ETL':<25} {'Query in place':<40}")
print(f"{'Joins':<25} {'Cross-catalog':<40}")
print(f"{'Real-time':<25} {'Fresh data':<40}")
print(f"{'Simplified':<25} {'One SQL':<40}")π Performance
π― Fast Analytics
Trino is designed for interactive performance β sub-second to minutes for queries on petabytes. Its MPP architecture, in-memory processing, and optimizations make it fast.
Performance
MPP: Parallel. In-memory: No disk. Pipeline: Streaming. Optimizer: Cost-based. Pushdown: Less I/O. Scale: Horizontal.
# Performance
print("=== Performance Features ===")
print("""
1. MPP ARCHITECTURE
- Parallel execution
- Scales horizontally
- Add workers
2. IN-MEMORY PROCESSING
- No disk shuffle (mostly)
- Low latency
- Fast
3. PIPELINE EXECUTION
- Streaming data
- No blocking
- Low latency
4. COST-BASED OPTIMIZER
- Choose best plan
- Join reordering
- Statistics
5. PREDICATE PUSHDOWN
- Filter at source
- Less I/O
- Faster
6. COLUMN PRUNING
- Read only needed
- Less I/O
7. PARTITION PRUNING
- Skip partitions
- Use metadata
""")
print("\n=== Performance Tuning ===")
print("""
1. PARTITIONS
- Partition tables
- Right cardinality
- Date-based
2. STATISTICS
- Collect stats
- ANALYZE TABLE
- Cost-based optimizer
3. WORKERS
- More workers
- More parallelism
- Right sizing
4. MEMORY
- Query memory
- Node memory
- Spill to disk
5. CONNECTORS
- Pushdown
- Parallel reads
- Split size
""")
print("\n=== Benchmarks ===")
print("""
TPC-H (1TB):
- Trino: ~1-5 minutes
- Hive: ~30+ minutes
- Spark: ~10-30 minutes
Interactive queries:
- Sub-second to seconds
- Petabyte scale
- Thousands of concurrent
Note: Performance depends on:
- Data layout
- Query complexity
- Cluster size
- Connectors
""")
print("\n=== When It's Fast ===")
print("""
FAST:
β Simple aggregations
β Selective filters
β Partitioned tables
β Columnar formats
β In-memory joins
SLOWER:
β Full table scans
β Cross-source joins
β Complex UDFs
β Skewed data
β Small files
""")
# IMPLEMENTATION
print("\n=== Simulating Performance ===")
class QueryPerformance:
"""Simulate query performance."""
def __init__(self, data_size_gb, num_workers, partitioned=True, columnar=True):
self.data_size_gb = data_size_gb
self.num_workers = num_workers
self.partitioned = partitioned
self.columnar = columnar
def estimate_time(self):
"""Estimate query time."""
# Base time
base = self.data_size_gb / 100 # 100 GB/s per worker
# Workers
parallel = base / self.num_workers
# Partitioning
if self.partitioned:
parallel *= 0.1 # 10x faster
# Columnar
if self.columnar:
parallel *= 0.3 # 3x faster
return parallel
def get_info(self):
return {
'data_gb': self.data_size_gb,
'workers': self.num_workers,
'partitioned': self.partitioned,
'columnar': self.columnar,
'estimated_seconds': self.estimate_time(),
}
# Demo
print("=== Performance Simulation ===")
scenarios = [
(1000, 4, False, False),
(1000, 4, True, False),
(1000, 4, True, True),
(1000, 16, True, True),
(10000, 16, True, True),
]
print(f"{'Data (GB)':<12} {'Workers':<10} {'Partitioned':<12} {'Columnar':<10} {'Est. Time':<15}")
print("-" * 65)
for data, workers, part, col in scenarios:
qp = QueryPerformance(data, workers, part, col)
info = qp.get_info()
print(f"{info['data_gb']:<12} {info['workers']:<10} {str(info['partitioned']):<12} "
f"{str(info['columnar']):<10} {info['estimated_seconds']:.2f}s")
# PERFORMANCE SUMMARY
print("\n=== Performance Summary ===")
print(f"{'Factor':<25} {'Impact':<40}")
print("-" * 65)
print(f"{'MPP':<25} {'High':<40}")
print(f"{'In-memory':<25} {'High':<40}")
print(f"{'Pipeline':<25} {'Medium':<40}")
print(f"{'Optimizer':<25} {'High':<40}")
print(f"{'Pushdown':<25} {'High':<40}")
print(f"{'Partitioning':<25} {'High':<40}")
print(f"{'Columnar':<25} {'High':<40}")π’ Deployment
π― Running Trino
Trino can be deployed in many ways: local, on-premise, cloud, Kubernetes, or managed services like Starburst. It's flexible.
Deployment
Local: Development. On-prem: Self-managed. Cloud: AWS, GCP, Azure. K8s: Kubernetes. Managed: Starburst. Flexible: Any way.
# Deployment Options
print("=== Deployment Options ===")
print("""
1. LOCAL
- Development
- Single machine
- Docker
docker run -p 8080:8080 trinodb/trino
2. ON-PREMISE
- Self-managed
- Multiple nodes
- Coordinator + workers
3. CLOUD
- AWS (EMR, EC2)
- GCP (Dataproc)
- Azure (HDInsight)
4. KUBERNETES
- Helm chart
- Trino operator
- Auto-scaling
5. MANAGED
- Starburst
- Ahana (Presto)
- AWS Athena (Presto-based)
""")
print("\n=== Configuration ===")
print("""
# etc/config.properties (Coordinator)
coordinator=true
node-scheduler.include-coordinator=false
http-server.http.port=8080
discovery.uri=http://coordinator:8080
# etc/config.properties (Worker)
coordinator=false
http-server.http.port=8080
discovery.uri=http://coordinator:8080
# etc/jvm.config
-Xmx16G
-XX:+UseG1GC
# etc/node.properties
node.environment=production
node.id=worker1
node.data-dir=/var/trino/data
""")
print("\n=== Cluster Sizing ===")
print("""
Coordinator:
- Medium instance
- 16-64 GB RAM
- 8-16 cores
- No data storage
Workers:
- Large instances
- 64-256 GB RAM
- 16-64 cores
- Memory for queries
Example:
- 1 coordinator
- 10-100 workers
- Scale based on data size
- Scale based on concurrency
""")
print("\n=== High Availability ===")
print("""
Coordinator HA:
- Multiple coordinators
- Active-passive
- Load balancer
- Shared state (optional)
Worker failures:
- Query fails
- Retry
- No data loss (connectors)
""")
# IMPLEMENTATION
print("\n=== Simulating Deployment ===")
class TrinoCluster:
"""Simulate Trino cluster."""
def __init__(self, name):
self.name = name
self.coordinator = None
self.workers = []
def deploy_coordinator(self, host='coordinator'):
"""Deploy coordinator."""
self.coordinator = {
'host': host,
'port': 8080,
'state': 'running',
}
print(f"Trino: Coordinator deployed at {host}:8080")
def deploy_worker(self, host, memory_gb=64):
"""Deploy worker."""
worker = {
'host': host,
'port': 8080,
'memory_gb': memory_gb,
'state': 'running',
}
self.workers.append(worker)
print(f"Trino: Worker deployed at {host} ({memory_gb} GB)")
def get_status(self):
return {
'name': self.name,
'coordinator': self.coordinator is not None,
'workers': len(self.workers),
'total_memory_gb': sum(w['memory_gb'] for w in self.workers),
}
# Demo
print("=== Deployment Demo ===")
cluster = TrinoCluster('production')
# Deploy
cluster.deploy_coordinator('trino-coordinator')
for i in range(1, 6):
cluster.deploy_worker(f'trino-worker-{i}', memory_gb=64)
# Status
print(f"\nCluster status: {cluster.get_status()}")
# DEPLOYMENT SUMMARY
print("\n=== Deployment Summary ===")
print(f"{'Option':<25} {'Use Case':<40}")
print("-" * 65)
print(f"{'Local':<25} {'Development':<40}")
print(f"{'On-prem':<25} {'Self-managed':<40}")
print(f"{'Cloud':<25} {'Managed infrastructure':<40}")
print(f"{'Kubernetes':<25} {'Container-native':<40}")
print(f"{'Starburst':<25} {'Managed service':<40}")π Security
π― Protecting Data
Trino supports authentication, authorization, encryption, and auditing. Enterprise features are available through Starburst.
Security
Authentication: Who are you? Authorization: What can you do? Encryption: Protect data. Auditing: Track access. LDAP: Directory. Kerberos: Enterprise.
# Security
print("=== Authentication ===")
print("""
Types:
- Password (LDAP, file)
- Kerberos
- JWT
- OAuth2
- Certificate
Configuration:
http-server.authentication.type=PASSWORD
http-server.authentication.password.user-file=etc/password.db
""")
print("\n=== Authorization ===")
print("""
System access control:
- Allow/deny catalogs
- Allow/deny schemas
- Allow/deny tables
- Row-level filters
- Column-level masks
File-based:
access-control.name=file
security.config-file=etc/rules.json
Example rules:
{
"catalogs": [
{
"catalog": "hive",
"users": ["admin"],
"allow": "all"
}
]
}
""")
print("\n=== Encryption ===")
print("""
TLS:
http-server.https.enabled=true
http-server.https.port=8443
http-server.https.keystore.path=etc/keystore.jks
Internal:
- TLS between nodes
- internal-communication.shared-secret
Connectors:
- Encrypted connections
- SSL/TLS
""")
print("\n=== Auditing ===")
print("""
Event listeners:
- Query events
- Access events
- Log to file
- Send to external
Configuration:
event-listener.properties
event-listener.name=...
Starburst:
- Built-in auditing
- Query history
- Access logs
""")
print("\n=== Best Practices ===")
print("""
1. Enable authentication
2. Use authorization
3. Encrypt connections
4. Audit access
5. Least privilege
6. Rotate credentials
7. Monitor
""")
# SECURITY SUMMARY
print("\n=== Security Summary ===")
print(f"{'Area':<25} {'Description':<40}")
print("-" * 65)
print(f"{'Authentication':<25} {'Verify identity':<40}")
print(f"{'Authorization':<25} {'Control access':<40}")
print(f"{'Encryption':<25} {'TLS, SSL':<40}")
print(f"{'Auditing':<25} {'Track access':<40}")
print(f"{'Row-level':<25} {'Filters':<40}")
print(f"{'Column-level':<25} {'Masks':<40}")βοΈ Presto vs Trino
π― The Two Projects
Presto and Trino share a common ancestry but have diverged. Trino is the more active community version with more features and connectors.
Comparison
Presto: Facebook, foundation. Trino: Community, active. Compatibility: Mostly same. Features: Trino ahead. Connectors: Trino more. Adoption: Both.
# Presto vs Trino
print("=== Comparison ===")
print(f"{'Aspect':<25} {'PrestoDB':<25} {'Trino':<25}")
print("-" * 75)
print(f"{'Governance':<25} {'Presto Foundation':<25} {'Trino Foundation':<25}")
print(f"{'Creator':<25} {'Facebook':<25} {'Original team':<25}")
print(f"{'Community':<25} {'Smaller':<25} {'Larger':<25}")
print(f"{'Development':<25} {'Active':<25} {'Very active':<25}")
print(f"{'Features':<25} {'Stable':<25} {'Cutting-edge':<25}")
print(f"{'Connectors':<25} {'Many':<25} {'Many + more':<25}")
print(f"{'Adoption':<25} {'Enterprise':<25} {'Broad':<25}")
print(f"{'Managed':<25} {'Ahana':<25} {'Starburst':<25}")
print(f"{'License':<25} {'Apache 2.0':<25} {'Apache 2.0':<25}")
print("\n=== Compatibility ===")
print("""
SQL:
- Mostly compatible
- Trino has extensions
Connectors:
- Similar names
- Configuration similar
Migration:
- Presto β Trino possible
- SQL compatible
- Connector compatible
Differences:
- Function names
- Configuration
- Some features
""")
print("\n=== Which to Choose ===")
print("""
CHOOSE PRESTO IF:
- You use Facebook's ecosystem
- Ahana support
- Existing Presto investment
CHOOSE TRINO IF:
- You want active community
- Latest features
- Starburst support
- Most users
DEFAULT:
- Trino is the modern choice
- More active
- More connectors
- Better community
""")
print("\n=== Migration ===")
print("""
Presto β Trino:
1. Update JDBC driver
2. Update SQL (minor)
3. Update connectors
4. Update configuration
5. Test
6. Deploy
Mostly straightforward.
""")πΌ Use Cases
π― Real-World Applications
Trino is used for interactive analytics, data lake queries, federated queries, and more across industries.
Use Cases
Analytics: Interactive queries. Data lake: Query S3. Federation: Join sources. BI: Dashboards. Ad-hoc: Exploration. Reporting: Scheduled.
# Use Cases
print("=== Industry Use Cases ===")
print(f"{'Industry':<20} {'Use Case':<35} {'Scale':<20}")
print("-" * 75)
print(f"{'E-commerce':<20} {'Product analytics':<35} {'Petabytes':<20}")
print(f"{'Finance':<20} {'Risk analysis':<35} {'Petabytes':<20}")
print(f"{'Media':<20} {'Content analytics':<35} {'Petabytes':<20}")
print(f"{'Healthcare':<20} {'Patient analytics':<35} {'Petabytes':<20}")
print(f"{'Telecom':<20} {'Network analytics':<35} {'Petabytes':<20}")
print(f"{'Tech':<20} {'Product analytics':<35} {'Petabytes':<20}")
print("\n=== 1. Interactive Analytics ===")
print("""
Use case:
- Ad-hoc queries
- Data exploration
- Dashboards
Value:
- Fast
- Petabyte scale
- No ETL
Example:
SELECT date, COUNT(*)
FROM s3.logs
WHERE date > '2024-01-01'
GROUP BY date;
""")
print("\n=== 2. Data Lake Queries ===")
print("""
Use case:
- Query S3 data
- No data movement
- Direct on Parquet/ORC
Value:
- No ETL
- Fresh data
- Cost-effective
Example:
SELECT * FROM hive.analytics.events
WHERE date = '2024-01-01';
""")
print("\n=== 3. Federated Queries ===")
print("""
Use case:
- Join across systems
- Single SQL
- No data movement
Value:
- Simplified
- Real-time
- Powerful
Example:
SELECT u.name, o.amount
FROM postgres.users u
JOIN hive.orders o ON u.id = o.user_id;
""")
print("\n=== 4. BI and Reporting ===")
print("""
Use case:
- Dashboards
- Reports
- KPIs
Value:
- Fast
- Interactive
- Connects to BI tools
Tools:
- Tableau
- Power BI
- Looker
- Superset
""")
print("\n=== 5. Ad-Hoc Exploration ===")
print("""
Use case:
- Data scientists
- Analysts
- Exploration
Value:
- Flexible
- Fast
- SQL
Example:
SELECT * FROM iceberg.events
WHERE user_id = 12345;
""")
# IMPLEMENTATION
print("\n=== Practical Example: E-commerce Analytics ===")
class EcommerceAnalytics:
"""Simulate e-commerce analytics with Trino."""
def __init__(self):
self.data = {
'users': [
{'id': 1, 'name': 'Alice', 'city': 'NYC'},
{'id': 2, 'name': 'Bob', 'city': 'LA'},
{'id': 3, 'name': 'Charlie', 'city': 'NYC'},
],
'orders': [
{'order_id': 101, 'user_id': 1, 'amount': 100, 'date': '2024-01-01'},
{'order_id': 102, 'user_id': 2, 'amount': 200, 'date': '2024-01-01'},
{'order_id': 103, 'user_id': 1, 'amount': 150, 'date': '2024-01-02'},
{'order_id': 104, 'user_id': 3, 'amount': 300, 'date': '2024-01-02'},
],
}
def query(self, sql):
"""Execute query (simplified)."""
print(f"Query: {sql[:60]}...")
# Simulate different queries
if 'GROUP BY city' in sql:
# Revenue by city
result = {}
for order in self.data['orders']:
user = next(u for u in self.data['users'] if u['id'] == order['user_id'])
city = user['city']
result[city] = result.get(city, 0) + order['amount']
return result
elif 'COUNT' in sql:
return {'count': len(self.data['orders'])}
return self.data
# Demo
print("=== E-commerce Analytics Demo ===")
analytics = EcommerceAnalytics()
# Query 1: Revenue by city
print("\n1. Revenue by city:")
result = analytics.query("SELECT city, SUM(amount) FROM orders GROUP BY city")
for city, revenue in result.items():
print(f" {city}: ${revenue}")
# Query 2: Count
print("\n2. Total orders:")
result = analytics.query("SELECT COUNT(*) FROM orders")
print(f" Count: {result['count']}")
# USE CASE SUMMARY
print("\n=== Use Case Summary ===")
print(f"{'Use Case':<25} {'Description':<40}")
print("-" * 65)
print(f"{'Interactive analytics':<25} {'Ad-hoc queries':<40}")
print(f"{'Data lake':<25} {'Query S3':<40}")
print(f"{'Federation':<25} {'Join sources':<40}")
print(f"{'BI':<25} {'Dashboards':<40}")
print(f"{'Ad-hoc':<25} {'Exploration':<40}")π vs Alternatives
π― Comparing Query Engines
Trino competes with Spark SQL, Hive, Impala, and cloud warehouses. Each has different strengths.
Alternatives
Trino: Interactive, federated. Spark: Batch + ML. Hive: Batch, mature. Impala: Cloudera. Warehouses: Managed. Choose: Based on needs.
# Trino vs Alternatives
print("=== Trino vs Spark SQL ===")
print(f"{'Aspect':<25} {'Trino':<20} {'Spark SQL':<20}")
print("-" * 65)
print(f"{'Primary use':<25} {'Interactive':<20} {'Batch + ML':<20}")
print(f"{'Latency':<25} {'Sub-second':<20} {'Seconds-minutes':<20}")
print(f"{'Federation':<25} {'Excellent':<20} {'Limited':<20}")
print(f"{'ML':<25} {'No':<20} {'Yes':<20}")
print(f"{'Memory':<25} {'In-memory':<20} {'In-memory + disk':<20}")
print(f"{'Ecosystem':<25} {'SQL':<20} {'Broad':<20}")
print("\n=== Trino vs Hive ===")
print(f"{'Aspect':<25} {'Trino':<20} {'Hive':<20}")
print("-" * 65)
print(f"{'Latency':<25} {'Sub-second':<20} {'Minutes':<20}")
print(f"{'Engine':<25} {'MPP':<20} {'MapReduce/Tez':<20}")
print(f"{'Federation':<25} {'Excellent':<20} {'Limited':<20}")
print(f"{'Maturity':<25} {'Modern':<20} {'Mature':<20}")
print(f"{'Use case':<25} {'Interactive':<20} {'Batch':<20}")
print("\n=== Trino vs Cloud Warehouses ===")
print(f"{'Aspect':<25} {'Trino':<20} {'Snowflake':<20} {'BigQuery':<20}")
print("-" * 75)
print(f"{'Open source':<25} {'Yes':<20} {'No':<20} {'No':<20}")
print(f"{'Federation':<25} {'Excellent':<20} {'Good':<20} {'Good':<20}")
print(f"{'Managed':<25} {'Starburst':<20} {'Yes':<20} {'Yes':<20}")
print(f"{'Cost':<25} {'Low':<20} {'High':<20} {'Pay per use':<20}")
print(f"{'Lock-in':<25} {'No':<20} {'Yes':<20} {'Yes':<20}")
print("\n=== When to Use Which ===")
print("""
TRINO:
β Interactive analytics
β Federation
β Data lake
β Open source
β No lock-in
SPARK SQL:
β Batch processing
β ML pipelines
β Complex ETL
β Unified analytics
HIVE:
β Batch processing
β Mature ecosystem
β Hadoop-native
CLOUD WAREHOUSES:
β Managed
β Serverless
β Easy
β But expensive
""")π Future
π― Where Trino Is Going
Trino is evolving: cloud-native, better performance, more connectors, and AI integration.
Future Directions
Cloud: Managed services. Performance: Faster. Connectors: More. AI: ML integration. Open: Standards. Unified: One platform.
# Future of Trino
print("=== 1. Cloud-Native ===")
print("""
Trend: Trino on cloud
Options:
- Starburst
- AWS EMR
- Google Dataproc
- Azure HDInsight
Benefits:
- No infrastructure
- Auto-scaling
- Pay per use
Future:
- Serverless Trino
- Event-driven
- Cost-effective
""")
print("\n=== 2. Performance ===")
print("""
Trend: Faster Trino
Features:
- Better optimizer
- Faster connectors
- Better memory
- Vectorized execution
Future:
- Sub-second at scale
- More concurrent
- Lower cost
""")
print("\n=== 3. More Connectors ===")
print("""
Trend: Connect to everything
Connectors:
- More databases
- More streaming
- More data lakes
- More APIs
Future:
- Universal connector
- Easy configuration
- Auto-discovery
""")
print("\n=== 4. AI and ML ===")
print("""
Trend: Trino for AI/ML
Features:
- ML functions
- Model inference
- Feature store
Future:
- SQL-based ML
- Model serving
- Feature engineering
""")
print("\n=== 5. Open Standards ===")
print("""
Trend: Open wins
Standards:
- Iceberg
- Delta
- Hudi
- OpenLineage
Future:
- Standardization
- Interoperability
- No lock-in
""")
# TIMELINE
print("\n=== Timeline ===")
print("""
Presto:
2012: Created
2013: Open sourced
2019: Foundation
Trino:
2019: Fork
2020: Renamed
2024: Active
Future:
2030: Serverless?
2035: AI-native?
2040: New paradigms?
""")
print("\n=== Final Thoughts ===")
print("""
Trino is:
- Distributed SQL
- Fast analytics
- Federated
- Open source
- Modern
The future is:
- Cloud-native
- Faster
- More connectors
- AI-ready
- Open
"Query everything, everywhere."
Keep exploring. Keep building.
""")