1 具体核心流程图介绍
2 详情分析
(1)HQL的执行形式
- 1)$HIVE_HOME/bin/hive 进入客户端,然后执行 HQL;
- 2)$HIVE_HOME/bin/hive -e “hql”;
- 3)$HIVE_HOME/bin/hive -f hive.sql;
- 4)先开启 hivesever2 服务端,然后通过 JDBC 方式连接远程提交 HQL。
可 以 知 道 我 们 执 行 HQL 主 要 依 赖 于 $HIVE_HOME/bin/hive 和 $HIVE_HOME/bin/
hivesever2 两种脚本来实现提交 HQL,而在这两个脚本中,最终启动的 JAVA 程序的主类为
“org.apache.hadoop.hive.cli.CliDriver”,所以其实 Hive 程序的入口就是“CliDriver”这个类。
(2)服务端接收到客户端的服务请求会启动一个CliDriver类。该类主要完成以下功能
1)解析客户端的-e,-f等参数
2)定义标准的输入输出流
3)按照;切分HQL语句。可以执行以分号隔开的多个SQL语句,按顺序执行
(3)创建Driver类
1)Hive语法解析器会将HQL语句按照词法、语法解析,翻译成抽象的语法树【AST】
2)将抽象的语法树转换成任务树【TaskTree】,调用分析器的方法
- 将抽象语法树转换为查询块【 QueryBlock】,可以理解为最小的查询单元
- 遍历查询块,将其转换为操作树【OperatorTree,逻辑执行单元】,可以理解为不可拆分的逻辑执行单元
- 使用逻辑优化器对操作树进行逻辑优化
- 遍历操作树,转换为任务数【TaskTree】。也就是翻译为MR任务流程,将逻辑执行计划转换为物理执行计划
- 使用物理执优化器对任务树进行物理优化
3)提交任务执行
生成最终的执行计划提交到Hadoop集群
- 1)获取MR临时工作目录
- 2)定义分区器【Partitioner】
- 3) 定义Mapper和Reducer
- 4)实例化job
- 5) 提交job
3 流程图
Hive SQL 编译成 MapReduce 过程
编译 SQL 的任务是在上节中介绍的 COMPILER(编译器组件)中完成的。Hive将SQL转化为MapReduce任务,整个编译过程分为六个阶段:
Hive SQL编译过程
- 词法、语法解析: Antlr 定义 SQL 的语法规则,完成 SQL 词法,语法解析,将 SQL 转化为抽象语法树 AST Tree;
Antlr是一种语言识别的工具,可以用来构造领域语言。使用Antlr构造特定的语言只需要编写一个语法文件,定义词法和语法替换规则即可,Antlr完成了词法分析、语法分析、语义分析、中间代码生成的过程。
- 语义解析: 遍历 AST Tree,抽象出查询的基本组成单元 QueryBlock;
- 生成逻辑执行计划: 遍历 QueryBlock,翻译为执行操作树 OperatorTree;
- 优化逻辑执行计划: 逻辑层优化器进行 OperatorTree 变换,合并 Operator,达到减少 MapReduce Job,减少数据传输及 shuffle 数据量;
- 生成物理执行计划: 遍历 OperatorTree,翻译为 MapReduce 任务;
- 优化物理执行计划: 物理层优化器进行 MapReduce 任务的变换,生成最终的执行计划。
下面对这六个阶段详细解析:
为便于理解,我们拿一个简单的查询语句进行展示,对5月23号的地区维表进行查询:
select * from dim.dim_region where dt = '2021-05-23';
阶段一:词法、语法解析
根据Antlr定义的sql语法规则,将相关sql进行词法、语法解析,转化为抽象语法树AST Tree:
ABSTRACT SYNTAX TREE:
TOK_QUERY
TOK_FROM
TOK_TABREF
TOK_TABNAME
dim
dim_region
TOK_INSERT
TOK_DESTINATION
TOK_DIR
TOK_TMP_FILE
TOK_SELECT
TOK_SELEXPR
TOK_ALLCOLREF
TOK_WHERE
=
TOK_TABLE_OR_COL
dt
'2021-05-23'
阶段二:语义解析
遍历AST Tree,抽象出查询的基本组成单元QueryBlock:
AST Tree生成后由于其复杂度依旧较高,不便于翻译为mapreduce程序,需要进行进一步抽象和结构化,形成QueryBlock。
QueryBlock是一条SQL最基本的组成单元,包括三个部分:输入源,计算过程,输出。简单来讲一个QueryBlock就是一个子查询。
QueryBlock的生成过程为一个递归过程,先序遍历 AST Tree ,遇到不同的 Token 节点(理解为特殊标记),保存到相应的属性中。
阶段三:生成逻辑执行计划
遍历QueryBlock,翻译为执行操作树OperatorTree:
Hive最终生成的MapReduce任务,Map阶段和Reduce阶段均由OperatorTree组成。
基本的操作符包括:
- TableScanOperator
- SelectOperator
- FilterOperator
- JoinOperator
- GroupByOperator
- ReduceSinkOperator`
Operator在Map Reduce阶段之间的数据传递都是一个流式的过程。每一个Operator对一行数据完成操作后之后将数据传递给childOperator计算。
由于Join/GroupBy/OrderBy均需要在Reduce阶段完成,所以在生成相应操作的Operator之前都会先生成一个ReduceSinkOperator,将字段组合并序列化为Reduce Key/value, Partition Key。
阶段四:优化逻辑执行计划
Hive中的逻辑查询优化可以大致分为以下几类:
- 投影修剪
- 推导传递谓词
- 谓词下推
- 将Select-Select,Filter-Filter合并为单个操作
- 多路 Join
- 查询重写以适应某些列值的Join倾斜
阶段五:生成物理执行计划
生成物理执行计划即是将逻辑执行计划生成的OperatorTree转化为MapReduce Job的过程,主要分为下面几个阶段:
- 对输出表生成MoveTask
- 从OperatorTree的其中一个根节点向下深度优先遍历
- ReduceSinkOperator标示Map/Reduce的界限,多个Job间的界限
- 遍历其他根节点,遇过碰到JoinOperator合并MapReduceTask
- 生成StatTask更新元数据
- 剪断Map与Reduce间的Operator的关系
阶段六:优化物理执行计划
Hive中的物理优化可以大致分为以下几类:
- 分区修剪(Partition Pruning)
- 基于分区和桶的扫描修剪(Scan pruning)
- 如果查询基于抽样,则扫描修剪
- 在某些情况下,在 map 端应用 Group By
- 在 mapper 上执行 Join
- 优化 Union,使Union只在 map 端执行
- 在多路 Join 中,根据用户提示决定最后流哪个表
- 删除不必要的 ReduceSinkOperators
- 对于带有Limit子句的查询,减少需要为该表扫描的文件数
- 对于带有Limit子句的查询,通过限制 ReduceSinkOperator 生成的内容来限制来自 mapper 的输出
- 减少用户提交的SQL查询所需的Tez作业数量
- 如果是简单的提取查询,避免使用MapReduce作业
- 对于带有聚合的简单获取查询,执行不带 MapReduce 任务的聚合
- 重写 Group By 查询使用索引表代替原来的表
- 当表扫描之上的谓词是相等谓词且谓词中的列具有索引时,使用索引扫描
经过以上六个阶段,SQL 就被解析映射成了集群上的 MapReduce 任务。