想象你走进一个巨大的美食广场:二十个档口,有的卖烤肉,有的做拉面,有的出甜品。你要点一份“杭州客户的订单统计”,但数据散落在不同档口的账本里——你总不能每个档口都跑一遍,把账本抄回来自己算吧?Presto/Trino 就是这个美食广场的“一站式点单服务平台”。你只要在大厅的触屏上写下需求,调度台就会派跑腿小哥分头去各个档口取数据,回来拼成一道完整的菜端给你。它不自己做菜(不存储数据),但能让所有档口为你服务(跨源查询)。本文就带你逛逛这个“美食广场”,看看它的架构、连接器、优化器、内存管理,以及与“中央大厨房”Spark SQL 的分工,帮你用一套 SQL 查遍多源数据,简化数据分析架构。
掌握联邦查询引擎,是你面试中展现分布式系统设计能力的加分项,更是搭建企业统一数据入口、告别多套数据源杂糅的底气。
目录
可视化演示
展示Trino Coordinator+Workers MPP架构(SQL→解析→计划→调度→并行执行→汇总)、跨数据源联邦查询(Hive+MySQL+Kafka→Connector→JOIN→统一结果)与性能对比(MPP并行加速比+Trino vs Spark SQL延迟/吞吐/并发/容错),交互切换核心维度。
本节配有交互动效(进入视口后自动加载,约 3KB)。
Coordinator+Workers MPP架构 Coordinator:接收SQL→语法解析→逻辑/物理计划→任务调度,集群大脑 Workers:MPP并行执行Task,流水线push-based模型,数据不落盘 计算存储分离:查询引擎不持有数据,通过Connector访问异构数据源 MPP加速比:S(N)=N/(1+α(N-1)) | N=Worker数,α=串行比例 Coordinator调度+Workers并行=分布式MPP查询
架构原理:中央调度与分片执行
美食广场里,二十个档口各卖各的,你要一份“杭州订单 + 用户信息”的汇总,不可能每个档口都去问一遍。广场中央设了一个调度台:它先收下订单,扫一眼菜单,把任务拆成几张便签,交给几个跑腿小哥分头行动——有人去烤肉档取用户数据,有人去拉面档取订单数据,最后在调度台拼好菜端给你。整个过程,你只需要下这一次单。
Presto 就是这样一座“美食广场”级的分布式 SQL 查询引擎,但它自己不存储任何数据。集群里有两类角色:Coordinator(协调者)就是调度台,负责接收 SQL、解析成执行计划、把任务分发给 Worker;Worker(工作者)就是跑腿小哥,负责并行读取数据源中的分片(Split),完成过滤、聚合、连接等计算。Presto 后因商标问题改名为 Trino,社区主线延续,但大家习惯上仍称 Presto。
一条查询的生命周期大致是:客户端把 SQL 发给 Coordinator → Coordinator 经过词法/语法解析生成逻辑执行计划,再优化为物理执行计划 → 把计划切成多个可并行执行的 Task → 通过服务发现机制找到空闲 Worker 分发任务 → Worker 通过 Connector 从各数据源拉取数据并计算 → 结果以流水线方式回流汇总 → 返回给客户端。这种无共享架构让 Presto 可以线性扩展:加 Worker,查询更快。
所以,你对美食广场的感知只有一句“下单→上菜”,但调度台和小哥们在背后完成了一整出分头行动的交响。这正是 Presto 的设计哲学:对外是极简的 SQL 接口,对内是精巧的分布式流水协作。
- 查询计划耗时Coordinator 生成执行计划所花的时间,通常只有几毫秒,是查询开销中的小头
- 最慢 Worker 执行时间所有 Worker 中耗时最大的那个,决定了查询的天花板,这就是分布式系统里的木桶效应
- 结果汇聚耗时各 Worker 把计算结果汇总回 Coordinator 并传输给客户端的时间,数据量越大这一项越明显
Connector机制:连通一切数据源
每个档口的点餐方式都不一样:烤肉档要求报号,拉面档要手写单,甜品档只认扫码。调度台总不能为每个档口记一套规矩。于是每个档口门口挂了一个“点餐翻译器”:你按统一菜单点,翻译器把标准订单翻译成档口认得的语言,再把档口端出的菜品翻译成统一格式。
这个“点餐翻译器”就是 Presto 的 Connector(连接器)。它是连接 Presto 与具体数据源的插件化适配层,定义了统一的 SPI(服务提供接口)。目前社区有 50 多个官方和第三方 Connector,覆盖 MySQL、PostgreSQL、Hive、HDFS、Kafka、MongoDB、Elasticsearch 甚至远程 HTTP API。只要实现一套 SPI,任何数据源都能被 SQL 查询。
Connector 的核心抽象有三块:TableLayout(表布局,描述表如何分区、分桶)、Split(数据分片,描述一段可独立读取的数据范围)、PageSource(数据读取器,真正拉数据并转成 Presto 统一的行列格式)。查询时,Connector 的 getSplits 会把一张表按分区、文件块等拆成多个分片,Worker 并行拉取,互不干扰。
有了翻译器,无论档口背后是烤肉炉还是数据库,调度台看到的都是同样的标准菜单。Connector 让 Presto 的联邦查询能力变得“即插即用”:想接入新数据源?写个翻译器挂上去就行。
- 数据总大小被查询表在数据源侧的数据量,单位是字节,来自元数据统计或文件系统信息
- 分片目标大小每个 Split 的目标规模。Presto 默认约 64MB,这是并行度和调度开销之间的折中
- 分片数量数据总量除以分片大小,得到可并行执行的任务数,它直接决定了查询能利用多少个 Worker 并行处理
查询优化器:聪明的执行规划
一个经验丰富的调度员接到订单后,不会拔腿就跑。他会先盘算:客人要“杭州用户”的姓名和金额,那就让 MySQL 档口先把杭州的筛出来,只取两个字段,别把整本账本搬回来;两个档口的食材怎么合并最省事,是把小份的用户表搬到大份订单那边,还是两边都按用户编号分桶再拼。这些盘算,就是优化器。
Presto 的查询优化器基于关系代数做等价变换,目标是生成“最便宜”的物理执行计划。最核心的手段有两个:谓词下推和列裁剪。谓词下推把 WHERE 过滤条件尽可能下推到数据源或最底层算子执行,让数据在源头就被筛掉一部分;列裁剪则让每个算子只读取 SELECT 涉及的列,大幅减少 IO。此外还有 Join 重排:根据表大小选择 Broadcast Join(小表广播)或 Partitioned Join(分区匹配)。
CBO(基于成本的优化器)则进一步让选择变得“有据可依”:它依据表的统计信息(行数、字段基数、数据分布),为每个候选算子估算 CPU 开销与 IO 开销,求和得到整体成本,最终选取成本最小的执行计划。优化器会尝试多种等价执行计划,如同调度员在脑中模拟多条取餐路线。
一个聪明调度员的经验,被编码成了可计算的成本公式。优化器能自动替成千上万的查询“想清楚”,这也是为什么同样一条 SQL,Presto 常常比人肉写的流程快一个数量级。
- 算子输出行数每个执行算子预计产出的行数,来自表统计信息或采样估算,是成本计算的基础
- 单行 CPU 成本处理一行的计算开销权重,聚合、连接这类算子权重高,简单投影权重低
- 单字节 IO 成本每传输一个字节的网络和磁盘开销权重,跨节点传输时这一项会显著放大
- 求和取最小把计划中所有算子成本相加,得到整条计划的估算成本,优化器在多个候选计划中选最小者
内存管理:取餐台的生存法则
档口做好的菜不能直接砸到客人脸上,得放到取餐台暂存。取餐台就那么大,订单太多放不下怎么办?要么把菜直接倒掉(查询失败),要么把半成品搬到后面的储藏室(磁盘),等取餐台空出来再挪回来。Presto 选择了后者,这就是内存溢写(Spill)。
Presto 是内存优先的纯计算引擎,Worker 的内存被划分为多个池:系统内存池(System Pool)给调度和内部服务用;用户内存池(User Pool)存聚合、过滤、连接的中间结果;保留池(Reserved Pool)为突发大查询兜底。每个查询在单节点上有内存上限,超过即触发溢写或失败,避免一个查询吃光整个节点内存拖垮其他查询。
开启 spill 后,当 join、聚合等算子的中间结果超过内存阈值,Presto 会把溢出部分按顺序写到本地磁盘,需要时再读回来。虽然磁盘交换会变慢,但总比整个查询 OOM 崩掉好。核心参数有三个:query.max-memory-per-node(单查询单节点内存上限)、query.max-total-memory-per-node(含系统开销的总上限)、spill-enabled(是否开启溢写)。
取餐台的管理哲学是:宁可让部分菜品暂存储藏室,也不让整个美食广场因堆满菜品而瘫痪。合理配置内存池和溢写阈值,Presto 才能在高并发下既不 OOM 也不频繁落盘。
- 节点总内存一个 Worker 节点上的物理内存总量,Presto 只使用其中一部分,剩余留给操作系统和数据源客户端
- 可分配比例Presto 能用来做查询计算的内存比例,常见配置是 0.6 左右,太大会挤压系统进程
- 最大并发查询数同一时刻允许多少个查询共享这个节点的内存,由资源组和集群配置共同决定
- 除法得到单查询上限把总配额平均分给并发查询,得到每个查询的硬性内存天花板,超了就触发溢写或拒绝
与Spark对比:美食广场与中央大厨房
如果美食广场是“现点现做”,那还有一种“中央大厨房”模式:食材提前集中拉进厨房,一次性做成几千份盒饭,准备时间长但吞吐惊人。Presto 是前者,Spark SQL 是后者。你很难说谁更好,只能说谁更适合当下的订单——是等不及的单客,还是大批量团餐客户。
Presto 是 MPP(大规模并行处理)无状态查询引擎,Coordinator 分片调度、Worker 内存流水线计算,目标是把查询延迟压到秒级。Spark SQL 是批处理框架,基于 RDD/Dataset 的弹性调度,把一个任务切成多个 Stage 和 Task 迭代执行,牺牲一定的调度开销换取容错和稳定性,适合分钟级以上的大规模 ETL。
两者的差异落在地板与天花板:Presto 在 GB 到 TB 级交互查询上通常比 Spark 快 5 到 10 倍;但面对 PB 级数据、复杂多轮迭代、机器学习训练,Spark 的稳定性和生态更胜一筹。Presto 也能跑 INSERT INTO 做轻量 ETL,但复杂的数仓加工仍然是 Spark 的主场。选型时重点看三个维度:延迟要求、数据规模、计算复杂度。
美食广场和中央大厨房会长期共存:想吃一份热乎的餐前小点,找 Presto;要做三千份团餐,找 Spark。理解两者分工,才不会被“Presto 比 Spark 快”这种片面结论带偏。
- 计划耗时生成并优化执行计划的时间,Presto 是纯 SQL 引擎,这一项优化得极短
- 读取耗时从数据源拉取数据的时间,两者差别不大,但 Presto 的谓词下推能大幅压缩实际读取量
- Shuffle 耗时网络洗牌传输中间结果的时间,Presto 尽量用广播和本地计算减少它,Spark 在复杂聚合时则难以避免
- 计算耗时真正执行算子计算的时间,Spark 的迭代式模型在复杂多阶段计算上更有优势
性能调优:让每一单更快
排队高峰期,怎么让每个客人都更快拿到菜?多开几个取餐窗口(提高并行度),把爆款菜提前备好(缓存热数据),精确记下客人点的菜而不是“每样来一份”(分区与列裁剪),把顺路的订单合并配送(Join 优化)。美食广场的这些招数,Presto 也一一对应。
Presto 调优的第一步是看并行度。并行度受限于两个因素:总分片数 S 和 Worker 计算能力(核数 × Worker 数)。分片太少则 Worker 闲置,太多则调度开销上升,经验上让每个 Worker 处理的 split 数在 2 到 4 个。第二步是利用数据源的分区信息做分区裁剪:Hive 分区表只扫描命中分区,能省掉 90% 以上的 IO。
第三步是 Join 调优:小表 join 大表时把 join_distribution_type 设为 BROADCAST,小表广播到所有 Worker,避免大 Shuffle;大表 join 大表则用分区 Join,并根据 Join Key 的分布倾斜情况调整分区数。最后,热数据可以挂在分布式缓存层(如 Alluxio)或开启结果缓存,减少重复拉取底层存储的压力。
调优的本质是找到瓶颈在哪一个环节:是档口出菜慢(数据源 IO),还是跑腿小哥不够(并行度),还是取餐台太挤(内存)。对症下药,比盲目加机器更有效。
- 总分片数当前查询被 Connector 拆分出的 Split 总数,它决定了可切割出的最小并行任务个数
- 每 Worker 槽位数单个 Worker 能同时执行的 Task 数,约等于 CPU 核数,超卖反而会引入线程切换开销
- Worker 数量集群中参与本次查询的 Worker 节点总数,扩容是提升并行度最直接的手段
- 取较小值并行度被任务数和资源数中的短板约束,调优就是让两者匹配,避免任何一方成为瓶颈
资源隔离:多租户的秩序管理
美食广场最怕什么?一个网红档口排了一百号人,把通道堵死,其他客人全进不来。物业于是定规矩:每个档口最多同时接待几单,超出就排队;VIP 团餐可以插队,普通小单按顺序来。这样谁都挤不垮谁。
Presto 用“资源组”(Resource Group)实现多租户隔离。你可以在配置里定义组名、权重、并发上限和排队策略,再用正则或会话属性把不同业务的查询路由到对应组。比如 BI 组权重 10,临时查询组权重 2,高峰期临时大查询进队列,不能抢占 BI 的查询资源。
每个资源组有四个核心参数:hardConcurrencyLimit(组内最大并发运行数)、maxQueued(最大排队数)、maxRunning(含排队的最大总数)、schedulingWeight(调度权重,决定轮转分配时的资源比例)。调度器按权重在组间轮转分配槽位,权重高的组拿到更多并发。联邦查询集群往往被多个团队共享,没有资源组,一个跑偏的大查询就能拖垮全公司报表。
资源隔离不是简单的限流,而是“秩序”:让重要查询有保障,让临时任务不饿死,让集群在洪峰下依旧稳定。这也是 Presto 上生产环境的关键一步。
- 该组权重资源组 g 的调度权重,权重 10 的组理论上比权重 2 的组多分 5 倍资源
- 所有组权重之和同一父组下所有子组权重的总和,用作归一化的分母
- 集群总资源可供分配的槽位总数或内存池大小,是资源组的预算上限
- 相乘得到份额权重占比乘以总资源,就是该组在竞争时可期望获得的最大资源量
AI 应用场景
跨源实时报表平台
阶段:数据服务与查询加速
解决的问题:传统做法要把 MySQL 业务库、HDFS 日志、ClickHouse 指标定期同步到数仓才能联合分析,T+1 延迟且存储翻倍。Presto 直接跨源 Join,一条 SQL 实时出报表,省掉中间同步链路。
具体案例:电商大促看板需要展示“实时订单量 × 用户城市分布”,数据工程师用 Presto 一条 SQL 同时查询 MySQL 订单表和 Hive 用户维表,看板秒级刷新,不再依赖凌晨跑批。
即席数据探索分析
阶段:数据分析与探索
解决的问题:分析师临时想验证“北上广用户的客单价差异”,按传统流程提 ETL 需求要排期,等半天才能看到结果,探索思路被打断。
具体案例:分析师在 Superset 里输入 SELECT city, avg(amount) FROM mysql_orders JOIN hive_users ON ... GROUP BY city,Presto 秒级返回结果,让分析从“按天迭代”变成“实时对话”。
湖仓统一 SQL 访问层
阶段:数据平台架构
解决的问题:公司存储五花八门,业务方要学多种查询语法,权限也难以统一,运维成本居高不下。
具体案例:平台团队用 Presto 做统一 SQL 网关,上层 Tableau、Superset 只连一个 Presto JDBC 地址,底层 Hive、HDFS、MySQL、Kafka 任意切换对业务透明,新数据源接入只加一个 Connector。
Python 演示
import time # 模拟两个异构数据源: mysql_users 类似 MySQL 表, hdfs_orders 类似 HDFS 文件mysql_users = [ {"id": 1, "name": "Alice", "city": "杭州"}, {"id": 2, "name": "Bob", "city": "上海"}, {"id": 3, "name": "Carol", "city": "杭州"},] hdfs_orders = [ {"user_id": 1, "amount": 100}, {"user_id": 1, "amount": 200}, {"user_id": 2, "amount": 50},] def scan_with_predicate(data, column, value): # 模拟谓词下推: 在数据源端过滤, 而不是把全表拉回内存 return [row for row in data if row.get(column) == value] def federated_join(user_table, order_table, user_key, order_key, city_filter=None): # 第1步: 谓词下推, 在 MySQL 侧先过滤城市 if city_filter: user_table = scan_with_predicate(user_table, "city", city_filter) # 第2步: 构造 hash 索引, 模拟把小表广播到各分片 user_index = {row[user_key]: row for row in user_table} # 第3步: 遍历订单分片, 与用户索引做 join rows = [] for order in order_table: user = user_index.get(order[order_key]) if user: rows.append({**user, **order}) return rows if __name__ == "__main__": start = time.time() result = federated_join(mysql_users, hdfs_orders, "id", "user_id", city_filter="杭州") cost_ms = (time.time() - start) * 1000 print("联邦查询结果:", result) print("耗时: %.2f ms" % cost_ms)
def scan_with_predicate(data, column, value):定义了过滤函数,模拟数据源侧的谓词下推,让数据在源头先变少。return [row for row in data if row.get(column) == value]列表推导式逐行过滤,只保留城市匹配的用户记录。def federated_join(...)联邦查询主函数,接收两个“数据源”和关联键,模拟一条跨源 SQL 的执行过程。user_table = scan_with_predicate(user_table, "city", city_filter)先把杭州用户筛出来,相当于 WHERE city='杭州' 被推到了 MySQL 端执行。user_index = {row[user_key]: row for row in user_table}构建哈希索引,模拟 Presto 把小表广播到各分片后建立的内存查找表。user = user_index.get(order[order_key])扫描订单“分片”时,用 O(1) 哈希查找匹配用户,避免笛卡尔积式全表扫描。rows.append({**user, **order})将用户和订单字段拼接合并,模拟联邦查询最终把多源结果组装成宽表返回。
常见误区
误区“Presto 不是支持 SQL 吗?那它应该是个数据库,能直接把我 MySQL 的数据存进去,以后查询更快吧?”
正解Presto 是查询引擎,不是存储引擎。它像美食广场的调度台,只负责组织档口出菜,自己不留存任何食材(数据)。它不建表、不做事务、不承担数据持久化,所有数据仍留在原数据源中。想让它“存数据”,是把它当成 OLTP 数据库用了。
为何常见:很多工具号称“支持 SQL”就被误认为数据库,尤其 Presto 的 JDBC 连接方式与数据库客户端一模一样,容易让人混淆查询引擎与存储系统。
误区“Presto 和 Spark 都能写 SQL 查大数据,那选一个部署就行了,反正都能用。”
正解两者是不同物种:Presto 是面向低延迟交互查询的 MPP 引擎,Spark 是面向高吞吐批处理的弹性计算框架。就好比美食广场和中央大厨房,都能出菜,但一个讲究快,一个讲究量大。拿 Presto 跑 PB 级复杂 ETL 会因内存和稳定性吃紧,拿 Spark 做秒级报表则延迟不可接受。
为何常见:两者的 SQL 语法和 Hadoop 生态重叠很多,初学者容易只看到“都能查数”的表面,忽略了架构设计和延迟模型的本质差异。
误区“跨数据源 Join 不就是要先把每个表的数据都拉到 Presto 内存里,再慢慢做关联吗?”
正解如果那样做,Presto 早就被 IO 拖垮了。真实执行时,优化器会做谓词下推(在源头过滤)、列裁剪(只取需要的列)、部分聚合下推(在数据源预聚合),只在最终需要时才传输最小必要的数据。好比调度台不会让档口把整本账本搬来,只让报几个数字。
为何常见:人们习惯用“先把数据集中再处理”的单机思维理解分布式查询,忽略了现代查询引擎的推演式优化能力。
误区“把 Presto 的 query.max-memory-per-node 调得很大,查询就不会因为内存不足失败了,性能自然更好。”
正解内存上限调大确实能减少单查询 OOM,但会挤压并发查询的生存空间。真正的性能瓶颈往往不在内存上限,而在数据倾斜、Shuffle 开销、分片不均。正确做法是保持合理内存配额,开启 spill 作为兜底,再针对瓶颈做分区裁剪、Join 策略和并行度调优。
为何常见:内存容量是最直观可见的资源指标,调大数字立竿见影地减少报错,让人误以为一劳永逸,实际上只是把问题从“单查询失败”变成了“并发互相挤兑”。
面试题
Q1. Presto/Trino 中 Coordinator 的核心职责是什么?
- A.实际存储查询的所有数据
- B.解析 SQL 并生成执行计划← 正确答案
- C.把元数据持久化到本地磁盘
- D.代替数据源执行所有计算任务
答案:B。Coordinator 是调度台,负责接收 SQL、解析优化、生成执行计划和分发任务,它不存储数据也不做具体计算。A 错在 Presto 不存数据,C 错在元数据在数据源侧,D 错在计算由 Worker 完成。
Q2. 联邦查询的核心价值是什么?
- A.把全部数据复制到一个数据库
- B.用一套 SQL 查询多个异构数据源← 正确答案
- C.完全替代 OLTP 在线事务数据库
- D.只能查询 Hadoop 上的海量数据
答案:B。联邦查询的价值在于“一个入口查所有”——通过 Connector 屏蔽底层差异,用标准 SQL 同时查询 MySQL、HDFS、Kafka 等。A 是数据同步而非联邦查询,C 超出 Presto 能力边界,D 错误,Presto 支持几十种数据源。
Q3. Connector(连接器)在 Presto 中的作用是什么?
- A.负责集群内部节点网络通信
- B.把统一 SQL 翻译成数据源读写操作← 正确答案
- C.只负责把查询结果做可视化展示
- D.管理所有 Worker 节点的生命周期
答案:B。Connector 是“点餐翻译器”,实现 SPI 接口把 Presto 的统一 SQL 语义翻译成具体数据源的操作,并把数据转成 Presto 内部格式。A 是集群通信组件,C 是 BI 工具职责,D 是集群管理工具职责,均与 Connector 无关。
Q4. 谓词下推(Predicate Pushdown)指的是什么?
- A.把 WHERE 过滤下推到数据源提前过滤← 正确答案
- B.把过滤条件推送给客户端应用去执行
- C.等全部数据汇总后再统一进行过滤
- D.把 WHERE 子句改写成 HAVING 子句
答案:A。谓词下推是优化器把 WHERE 条件推向数据源或最底层算子,让数据在源头被裁剪,减少网络传输和内存占用。B 方向反了,C 是全量拉取再过滤的低效做法,D 把过滤语义改成分组后过滤,完全不是一回事。
Q5. 与 Spark SQL 相比,Presto/Trino 更适合哪种场景?
- A.大规模 ETL 批处理数据加工
- B.低延迟的交互式即席查询← 正确答案
- C.大规模深度学习模型训练
- D.高吞吐实时流式数据计算
答案:B。Presto 是 MPP 内存计算引擎,专为秒级交互查询设计,适合 BI 报表和即席分析。ETL 批处理是 Spark 的强项,模型训练需要 Spark MLlib 等生态,流式计算则应选 Flink 或 Spark Streaming,都不是 Presto 的主场。
Q6. Presto 发生内存溢出风险时,spill(溢写)机制的作用是什么?
- A.直接丢弃部分查询结果释放内存
- B.把中间结果溢写到磁盘继续计算← 正确答案
- C.自动重启内存不足的 Worker 节点
- D.缩小查询数据范围来规避内存不足
答案:B。spill 把超出内存阈值的 join、聚合中间结果暂存到本地磁盘,等内存有空再读回,以时间换空间避免 OOM。A 会丢数据,C 是集群运维手段,D 改变了查询语义,均不是溢写机制。
Q7. 实际执行查询任务并处理数据分片(Split)的是哪个组件?
- A.协调者节点负责全局调度
- B.工作者节点执行查询分片← 正确答案
- C.连接器负责打通数据源
- D.优化器负责生成执行计划
答案:B。Worker 是跑腿小哥,真正拉取 Split、执行过滤聚合连接并返回结果。Coordinator 只负责调度不干体力活,Connector 负责数据源适配,优化器是 Coordinator 内置的逻辑组件,都不直接执行分片计算。
Q8. Presto 查询优化器会做哪些典型优化?
- A.列裁剪只读取所需字段← 正确答案
- B.谓词下推提前过滤数据← 正确答案
- C.自动创建数据表结构
- D.重排连接减少网络传输← 正确答案
答案:ABD。列裁剪减少 IO,谓词下推在源头过滤,Join 重排(如选择 Broadcast 或 Partitioned Join)减少 Shuffle 开销,这些都是优化器的典型手段。自动建表是 DDL 操作,优化器不负责建表。
Q9. Presto 资源隔离的手段包括哪些?
- A.用资源组划分查询配额← 正确答案
- B.配置队列权重分配资源← 正确答案
- C.设置最大并发查询数量← 正确答案
- D.对数据传输进行加密处理
答案:ABC。资源组是 Presto 多租户隔离的核心,通过权重分配资源、通过并发上限控制洪峰。数据加密属于安全范畴,解决的是传输保密问题,不是资源隔离问题,因此 D 不选。
Q10. 关于 Presto/Trino 与 Spark SQL 的选型,哪些说法正确?
- A.亚秒级交互查询优先选用 Presto 引擎← 正确答案
- B.海量数据 ETL 批处理优先选择 Spark 引擎← 正确答案
- C.Presto 也能承担部分轻量 ETL 加工任务← 正确答案
- D.Spark 可完全替代 Presto 做联机交互查询
答案:ABC。Presto 主打低延迟交互,Spark 主打高吞吐批处理,两者互补而非替代。Presto 支持 INSERT INTO 语法,能做轻量 ETL。D 错误,Spark 的调度延迟和批处理模型无法胜任秒级联机查询,不能完全替代。