恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Hive 源码导读(三):都是 SELECT,为什么有的查询不需要 YARN?
首页
资讯中心
/
Hive 源码导读(三):都是 SELECT,为什么有的查询不需要 YARN?
Hive 源码导读(三):都是 SELECT,为什么有的查询不需要 YARN?
发布时间:2026/10/12 5:39:04
Hive 源码导读三都是 SELECT为什么有的查询不需要 YARN上一篇订单查询已经从 Beeline 到达了 Driver。我们先查了十条订单结果很快返回接着想知道当天已支付的订单一共多少钱写了一条聚合 SQL。这次日志里出现了 MR Job。都是SELECT为什么一条直接出结果另一条要安排计算任务答案藏在执行计划里。Hive 接收到 SQL 后要先把“你想做什么”翻译成“具体怎样做”再决定由谁执行。本文基于Hive 3.1.2、Hadoop 3.2.1MR on YARN。SQL 使用系列实验表。下文计划形状为解释性示意实际 Stage 编号和算子组合以本机EXPLAIN为准。一、今天把需求升级一下第一条查询只看订单明细SELECTorder_id,amount,statusFROMcsdn_hive_lab.orders_rawWHEREdt2026-10-09LIMIT10;第二条要统计不同状态的订单金额SELECTstatus,SUM(amount)AStotal_amountFROMcsdn_hive_lab.orders_rawWHEREdt2026-10-09GROUPBYstatus;对六行实验数据来说手工也能算出来。但 Hive 不能只凭 SQL 字符数安排工作它要识别过滤、分组、聚合以及读写对象再生成对应执行计划。二、先审需求再写施工单可以把编译理解为给需求写施工单主要分成几件事阶段用订单查询解释能发现的问题语法分析认出 SELECT、FROM、WHERE 等结构括号、关键字或语法位置不对语义分析找订单表检查 amount 是否存在、能否求和表不存在、字段不存在、类型不合适生成和优化计划安排读取、过滤、分组和输出是否可以少读分区、少传字段、改变算子组织形成执行任务为当前引擎组织能够执行的工作用哪些 Hive Task任务怎样依赖AST 就是语法分析得到的树形结构。初学时不用记它每一种节点只要知道Hive 已经把字符串变成了能继续分析的结构。语义分析为什么要访问 Metastore因为光看 SQL编译器不知道orders_raw里面有什么字段、哪些分区存在、文件按什么格式保存。没有 Application却在访问 Metastore一点也不矛盾。它可能还在准备施工单。三、源码不用一口气追到底第一轮阅读可以沿着这几个位置走Driver.compile() → 语法解析相关入口ParseUtils / ParseDriver → SemanticAnalyzerFactory 选择分析器 → 语义分析、优化与任务生成 → QueryPlan实际编译流程包含权限检查、Hook、统计信息、优化器与不同语句分支。这里保留的是理解方向所需的骨架并不是完整调用栈。SemanticAnalyzer会处理查询的语义和计划。TaskCompiler及其引擎相关实现则帮助把计划组织成可执行的任务。读源码时先观察计划输入和输出发生了什么变化再深入某一种优化。例如WHERE dt2026-10-09提供了明确的分区条件。它的价值是让系统有机会只访问这一天对应的分区。至于读取阶段是否又做了其他过滤要继续看计划和存储格式。四、Operator、Hive Task、MR Task 别混在一起这三个名字都与“干活”有关却不在同一层。名字可以怎样理解例子Operator一项数据处理动作扫描、过滤、选择字段、分组Hive TaskHive 安排的执行单元MR 任务、DDL 任务、MoveTaskMR Task一个 MR Job 内部的计算任务某个 Map Task、Reduce Task所以EXPLAIN里出现一个 Stage不代表只启动一个进程一段 Map 算子树也不是说集群上只能有一个 Map Task。可以把 Operator 理解为施工动作Hive Task 理解为一项施工安排MR Task 则是引擎真正拆出去执行的工作。五、FetchTask 为什么能省掉一次分布式提交SimpleFetchOptimizer的工作是检查某些简单查询能否直接转成 FetchTask。读transform()和optimize()重点看两个判断算子树能不能直接读取相关阈值条件是否满足。下面是依据源码整理的伪代码// 解释性伪代码省略具体类型与分支。if(queryCanUseFetchoperatorTreeCanUseFetchthresholdAllows){plan.setFetchTask(createFetchTask());}转换成功后HS2 可以在这个执行路径上直接读表或分区的数据。开头那条“指定分区、选择几个字段、LIMIT 10”的查询就是适合观察这种优化的小案例。但不能把它记成“带 LIMIT 就不走 MR”。连接、聚合、表的能力、优化规则和配置都会影响结果。反过来计划里有 Fetch Operator也不表示从来没有分布式计算MR 结果返回客户端时同样可能需要 FetchTask。要看整个计划有没有 MR 阶段以及 FetchTask 读的是源表还是前序结果。六、让同一条 SQL 换一次执行路线先在实验会话里确认引擎与运行方式SEThive.execution.enginemr;SETmapreduce.framework.name;SEThive.exec.mode.local.autofalse;SEThive.fetch.task.conversion;mapreduce.framework.name应来自已正确配置的环境并显示为yarn。只设置 Hive 的mr不能替代 Hadoop 客户端的完整配置。先打开简单查询转换查看计划SEThive.fetch.task.conversionmore;EXPLAINSELECTorder_id,amount,statusFROMcsdn_hive_lab.orders_rawWHEREdt2026-10-09LIMIT10;再关闭转换查看同一条查询SEThive.fetch.task.conversionnone;EXPLAINSELECTorder_id,amount,statusFROMcsdn_hive_lab.orders_rawWHEREdt2026-10-09LIMIT10;我们要比较的是 MR 阶段、算子树和读取位置而不是要求两份输出必须出现固定的 Stage 编号。EXPLAIN自己通常只生成计划并不会替你执行这条业务查询要观察提交行为还要执行相应的 SELECT。完成对比后把hive.fetch.task.conversion恢复到实验前记录的值。别把为了观察路径而调整的参数顺手带进其他任务。七、先学会看三样东西就够了一份很长的计划第一遍只看从哪里读源表、目标分区、扫描条件是否符合预期。中间做什么有没有分组、Reduce Output、连接等需要关注的算子。任务怎样接起来有哪些 Stage、依赖关系如何、最终结果由谁输出。对于订单按状态求和可以先把逻辑理解成读指定日期的订单 → 按 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.javaFetch 转换条件。FetchTask、HiveConf直接读取与相关配置。上一篇 · 下一篇MR 怎样提交到 YARN后续更新可从专栏目录查看