1. 简介
主要介绍Hive的parse enginer(包括HQL->TaskTree)
Hive版本:1.2.1
HiBench 版本: v6
Hadoop 版本: 2.7.1
2. Hive 与 传统RDBMS的区别
3. Hive架构
4. Hive 源码中3个关键的部分 (version Hive-1.2.1):
Hive核心三大组件
Query Processor:查询处理工具,源码ql包
SerDe:序列化与反序列化器,源码serde包
MetaStore:元数据存储及服务,源码metastore包
SerDe所处的位置
源码ql包下的子目录:
parse目录包含了解析HQL语句到 TaskTree的主线代码
optimizer目录提供了optimzer相关的接口
exec目录提供了task层的接口封装.例如,sparktask
plan 目录提供了work层的接口封装.例如,reducework
udf目录提供了查询用的自定义函数,例如简单的计算
5. HQL转化为MapReduce的6个过程
5.1 Hive是如何将HQL转化为MapReduce任务的,整个编译过程分为六个阶段:
1. Antlr定义SQL的语法规则,完成SQL词法,语法解析,将SQL转化为抽象语法树AST Tree
2. 遍历AST Tree,抽象出查询的基本组成单元QueryBlock
3. 遍历QueryBlock,翻译为执行操作树OperatorTree
4. 逻辑层优化器进行OperatorTree变换,合并不必要的ReduceSinkOperator,减少shuffle数据量
5. 遍历OperatorTree,翻译为MapReduce任务
6. 物理层优化器进行MapReduce任务的变换,生成最终的执行计划
5.2 源代码简要分析六个阶段:
5.2.1 ParseDriver(包含Phase1)
这个类是解析sql的入口. HiveLexerX,HiveParser分别是Antlr对语法文件HiveLexer.g编译后自动生成的词法解析和语法解析类,在这两个类中进行复杂的解析。
5.2.2一颗抽象语法树变成一个QB(query block) SemanticAnalyzer.java (语义分析器)(包含Phase2-6)
6. 详细解释HQL转化为MapReduce的过程
6.1. Phase1 SQL词法,语法解析
Hive使用Antlr实现SQL的词法和语法解析。Antlr是一种语言识别的工具,可以用来构造领域语言。
6.2. Phase2 SQL基本组成单元QueryBlock
AST Tree仍然非常复杂,不够结构化,不方便直接翻译为MapReduce程序,AST Tree转化为QueryBlock就是将SQL进一部抽象和结构化. QueryBlock是一条SQL最基本的组成单元,包括三个部分:输入源,计算过程,输出。简单来讲一个QueryBlock就是一个子查询。
下图为Hive中QueryBlock相关对象的类图,解释图中几个重要的属性
AST Tree生成QueryBlock
AST Tree生成QueryBlock的过程是一个递归的过程,先序遍历AST Tree,遇到不同的Token节点,保存到相应的属性中,主要包含以下几个过程
• TOK_QUERY => 创建QB对象,循环递归子节点
• TOK_FROM => 将表名语法部分保存到QB对象的aliasToTabs等属性中
• TOK_INSERT => 循环递归子节点
• TOK_DESTINATION => 将输出目标的语法部分保存在QBParseInfo对象的nameToDest属性中
• TOK_SELECT => 分别将查询表达式的语法部分保存在destToSelExpr、destToAggregationExprs、destToDistinctFuncExprs三个属性中
• TOK_WHERE => 将Where部分的语法保存在QBParseInfo对象的destToWhereExpr属性中
最终样例SQL生成两个QB对象,QB对象的关系如下,QB1是外层查询,QB2是子查询
QB1
\
QB2
6.3. Phase3 逻辑操作符Operator
Hive最终生成的MapReduce任务,Map阶段和Reduce阶段均由OperatorTree组成。逻辑操作符,就是在Map阶段或者Reduce阶段完成单一特定的操作。基本的操作符包括TableScanOperator,SelectOperator,FilterOperator,JoinOperator,GroupByOperator,ReduceSinkOperator. ReduceSinkOperator将Map端的字段组合序列化为Reduce Key/value, Partition Key,只可能出现在Map阶段,同时也标志着Hive生成的MapReduce程序中Map阶段的结束。
由于Hive的MapReduce程序是一个动态的程序,即不确定一个MapReduce Job会进行什么运算,可能是Join,也可能是GroupBy,所以Operator将所有运行时需要的参数保存在OperatorDesc中,OperatorDesc在提交任务前序列化到HDFS上,在MapReduce任务执行前从HDFS读取并反序列化。Map阶段OperatorTree在HDFS上的位置在Job.getConf(“hive.exec.plan”) + “/map.xml”
QueryBlock生成Operator Tree
QueryBlock生成Operator Tree就是遍历上一个过程中生成的QB和QBParseInfo对象的保存语法的属性,包含如下几个步骤:
• QB#aliasToSubq => 有子查询,递归调用
• QB#aliasToTabs => TableScanOperator
• QBParseInfo#joinExpr => QBJoinTree => ReduceSinkOperator + JoinOperator
• QBParseInfo#destToWhereExpr => FilterOperator
• QBParseInfo#destToGroupby => ReduceSinkOperator + GroupByOperator
• QBParseInfo#destToOrderby => ReduceSinkOperator + ExtractOperator
由于Join/GroupBy/OrderBy均需要在Reduce阶段完成,所以在生成相应操作的Operator之前都会先生成一个ReduceSinkOperator,将字段组合并序列化为Reduce Key/value, Partition Key.
Operators对应SQL
Operator过程
每个步骤对应一个逻辑运算符(Operator)
每个Operator输出一个虚表(VirtualTable)
6.4. Phase4 逻辑层优化器
大部分逻辑层优化器通过变换OperatorTree,合并操作符,达到减少MapReduce Job,减少shuffle数据量的目的。
名称 作用
② SimpleFetchOptimizer 优化没有GroupBy表达式的聚合查询
② MapJoinProcessor MapJoin,需要SQL中提供hint,0.11版本已不用
② BucketMapJoinOptimizer BucketMapJoin
② GroupByOptimizer Map端聚合
① ReduceSinkDeDuplication 合并线性的OperatorTree中partition/sort key相同的reduce
① PredicatePushDown 谓词前置
① CorrelationOptimizer 利用查询中的相关性,合并有相关性的Job,HIVE-2206
ColumnPruner 字段剪枝
表格中①的优化器均是一个Job干尽可能多的事情/合并。②的都是减少shuffle数据量,甚至不做Reduce。
PredicatePushDown优化器
断言判断提前优化器将OperatorTree中的FilterOperator提前到TableScanOperator之后
NonBlockingOpDeDupProc优化器
NonBlockingOpDeDupProc优化器合并SEL-SEL 或者 FIL-FIL 为一个Operator
6.5. Phase5 OperatorTree生成TaskTree(MapReduce Job)的过程<