Hive 源码导读(三):都是 SELECT,为什么有的查询不需要 YARN?

Hive 源码导读(三):都是 SELECT,为什么有的查询不需要 YARN?

上一篇,订单查询已经从 Beeline 到达了 Driver。

我们先查了十条订单,结果很快返回;接着想知道当天已支付的订单一共多少钱,写了一条聚合 SQL。这次,日志里出现了 MR Job。

都是 SELECT,为什么一条直接出结果,另一条要安排计算任务?

答案藏在执行计划里。Hive 接收到 SQL 后,要先把"你想做什么"翻译成"具体怎样做",再决定由谁执行。

本文基于 Hive 3.1.2、Hadoop 3.2.1,MR on YARN 。SQL 使用系列实验表。下文计划形状为解释性示意,实际 Stage 编号和算子组合以本机 EXPLAIN 为准。

一、今天把需求升级一下

第一条查询只看订单明细:

sql 复制代码
SELECT order_id, amount, status
FROM csdn_hive_lab.orders_raw
WHERE dt='2026-10-09'
LIMIT 10;

第二条要统计不同状态的订单金额:

sql 复制代码
SELECT status, SUM(amount) AS total_amount
FROM csdn_hive_lab.orders_raw
WHERE dt='2026-10-09'
GROUP BY status;

对六行实验数据来说,手工也能算出来。但 Hive 不能只凭 SQL 字符数安排工作;它要识别过滤、分组、聚合以及读写对象,再生成对应执行计划。

二、先审需求,再写施工单

可以把编译理解为给需求写施工单,主要分成几件事:

阶段 用订单查询解释 能发现的问题
语法分析 认出 SELECT、FROM、WHERE 等结构 括号、关键字或语法位置不对
语义分析 找订单表,检查 amount 是否存在、能否求和 表不存在、字段不存在、类型不合适
生成和优化计划 安排读取、过滤、分组和输出 是否可以少读分区、少传字段、改变算子组织
形成执行任务 为当前引擎组织能够执行的工作 用哪些 Hive Task,任务怎样依赖

AST 就是语法分析得到的树形结构。初学时不用记它每一种节点,只要知道:Hive 已经把字符串变成了能继续分析的结构。

语义分析为什么要访问 Metastore?因为光看 SQL,编译器不知道 orders_raw 里面有什么字段、哪些分区存在、文件按什么格式保存。

没有 Application,却在访问 Metastore,一点也不矛盾。它可能还在准备施工单。

三、源码不用一口气追到底

第一轮阅读,可以沿着这几个位置走:

text 复制代码
Driver.compile()
  → 语法解析相关入口(ParseUtils / ParseDriver)
  → SemanticAnalyzerFactory 选择分析器
  → 语义分析、优化与任务生成
  → QueryPlan

实际编译流程包含权限检查、Hook、统计信息、优化器与不同语句分支。这里保留的是理解方向所需的骨架,并不是完整调用栈。

SemanticAnalyzer 会处理查询的语义和计划。TaskCompiler 及其引擎相关实现,则帮助把计划组织成可执行的任务。读源码时,先观察计划输入和输出发生了什么变化,再深入某一种优化。

例如 WHERE dt='2026-10-09' 提供了明确的分区条件。它的价值是让系统有机会只访问这一天对应的分区。至于读取阶段是否又做了其他过滤,要继续看计划和存储格式。

四、Operator、Hive Task、MR Task 别混在一起

这三个名字都与"干活"有关,却不在同一层。

名字 可以怎样理解 例子
Operator 一项数据处理动作 扫描、过滤、选择字段、分组
Hive Task Hive 安排的执行单元 MR 任务、DDL 任务、MoveTask
MR Task 一个 MR Job 内部的计算任务 某个 Map Task、Reduce Task

所以 EXPLAIN 里出现一个 Stage,不代表只启动一个进程;一段 Map 算子树,也不是说集群上只能有一个 Map Task。

可以把 Operator 理解为施工动作,Hive Task 理解为一项施工安排,MR Task 则是引擎真正拆出去执行的工作。

五、FetchTask 为什么能省掉一次分布式提交

SimpleFetchOptimizer 的工作,是检查某些简单查询能否直接转成 FetchTask。

读 transform() 和 optimize(),重点看两个判断:算子树能不能直接读取,相关阈值条件是否满足。下面是依据源码整理的伪代码:

java 复制代码
// 解释性伪代码:省略具体类型与分支。
if (queryCanUseFetch && operatorTreeCanUseFetch && thresholdAllows) {
    plan.setFetchTask(createFetchTask());
}

转换成功后,HS2 可以在这个执行路径上直接读表或分区的数据。开头那条"指定分区、选择几个字段、LIMIT 10"的查询,就是适合观察这种优化的小案例。

但不能把它记成"带 LIMIT 就不走 MR"。连接、聚合、表的能力、优化规则和配置都会影响结果。

反过来,计划里有 Fetch Operator,也不表示从来没有分布式计算:MR 结果返回客户端时同样可能需要 FetchTask。要看整个计划有没有 MR 阶段,以及 FetchTask 读的是源表还是前序结果。

六、让同一条 SQL 换一次执行路线

先在实验会话里确认引擎与运行方式:

sql 复制代码
SET hive.execution.engine=mr;
SET mapreduce.framework.name;
SET hive.exec.mode.local.auto=false;
SET hive.fetch.task.conversion;

mapreduce.framework.name 应来自已正确配置的环境,并显示为 yarn。只设置 Hive 的 mr,不能替代 Hadoop 客户端的完整配置。

先打开简单查询转换,查看计划:

sql 复制代码
SET hive.fetch.task.conversion=more;

EXPLAIN
SELECT order_id, amount, status
FROM csdn_hive_lab.orders_raw
WHERE dt='2026-10-09'
LIMIT 10;

再关闭转换,查看同一条查询:

sql 复制代码
SET hive.fetch.task.conversion=none;

EXPLAIN
SELECT order_id, amount, status
FROM csdn_hive_lab.orders_raw
WHERE dt='2026-10-09'
LIMIT 10;

我们要比较的是 MR 阶段、算子树和读取位置,而不是要求两份输出必须出现固定的 Stage 编号。EXPLAIN 自己通常只生成计划,并不会替你执行这条业务查询;要观察提交行为,还要执行相应的 SELECT。

完成对比后,把 hive.fetch.task.conversion 恢复到实验前记录的值。别把为了观察路径而调整的参数顺手带进其他任务。

七、先学会看三样东西就够了

一份很长的计划,第一遍只看:

  1. 从哪里读:源表、目标分区、扫描条件是否符合预期。
  2. 中间做什么:有没有分组、Reduce Output、连接等需要关注的算子。
  3. 任务怎样接起来:有哪些 Stage、依赖关系如何、最终结果由谁输出。

对于订单按状态求和,可以先把逻辑理解成:

text 复制代码
读指定日期的订单
  → 按 status 组织分组
  → 对 amount 求和
  → 输出各状态金额

是否存在 Map 端局部聚合、多少个 Reduce,以及最终 Stage 形状,都交给具体执行计划回答。别把"GROUP BY 永远恰好一个固定样子的 MR"当成规则。

八、没有 Application 时,多想一步

证据 更合理的下一步
最终计划不需要 MR 沿元数据或直接读取路径查看完成状态
计划包含 MR,但日志仍在编译 查看元数据访问、编译耗时与相关等待
已编译,正在申请锁 检查锁对象、持有者与等待状态
已进入 Job 提交,却暂时没有应用 检查提交准备、HDFS staging、客户端与 RM 通信

最后两行先在这里留个位置。锁会在第五篇展开;下一篇,我们先陪着已经生成的 MR 工作单,走到 YARN 门口。

本篇关键源码位置

  • Driver.java:编译与 QueryPlan。
  • ParseDriver、SemanticAnalyzerFactory、SemanticAnalyzer:解析与分析。
  • TaskCompiler、MapReduceCompiler:引擎任务生成。
  • SimpleFetchOptimizer.java:Fetch 转换条件。
  • FetchTask、HiveConf:直接读取与相关配置。

上一篇 · 下一篇:MR 怎样提交到 YARN(后续更新,可从专栏目录查看)

相关推荐
注塑机数据采集联网16 小时前
数据采集网关入门:ZK-D1/D3从零开始构建你的数据运用
大数据·数据仓库·人工智能·物联网·数据库架构·注塑机网关
测试盐21 小时前
spark作业日志定位过程
java·hadoop·spark
roman_日积跬步-终至千里1 天前
【数据建模入门】从一家小店看懂数仓与机器学习:先理业务,再串技术
数据仓库·人工智能·机器学习·数据分析·数据建模
步行cgn1 天前
为什么既要 web.xml 又要 springmvc.xml?能不能只配一个?
xml·前端·hive
程序员梅雨2 天前
【从零开始学习数据仓库 | 第二篇】: 拉链表 & 数仓分层
大数据·数据仓库·学习
NiceZack2 天前
Hadoop 部署全流程教程:从新装 CentOS 到伪分布式与完全分布式
hadoop·分布式·centos
roman_日积跬步-终至千里2 天前
数仓开发的三层责任:业务定义、模型设计与 SQL 实现
数据库·数据仓库·sql·数据建模
@小匠2 天前
Flink + Iceberg 批量失败复盘:一次超时如何变成 Hive Metastore 锁泄漏
大数据·hive·flink
geovindu3 天前
SQL Data Sampling and Approximation Techniques using postgreSQL 18
大数据·数据库·数据仓库·sql·postgresql·数据库开发·数据库架构
skywalk81633 天前
hive —— 多机 AI Agent 协同的任务总线:分布式,多节点同时运行,保障不会宕机
人工智能·hive·分布式