Hive SQL 语义分析:select count(*) from tableName

从客户端提交一个 Hive SQL  到 Driver 提交 MapReduce Job,有一个对SQL进行词法分析和语义分析的过程,下面以 select count(*) from tableName 来描述其过程。

一、词法分析

使用ANTLR分析SQL,生成语法树,每个节点是一个 ASTNode,它有自己的类型。

来看看 select count(*) from tableName 的语法树:

(
TOK_QUERY 
	(
	TOK_FROM 
		(
		TOK_TABREF 
			(
			TOK_TABNAME 
				   tt2
			)
		)
	) 
	(
	TOK_INSERT 
		(
		TOK_DESTINATION 
			(
			TOK_DIR 
				TOK_TMP_FILE
			)
		) 
		(
		TOK_SELECT 
			(
			TOK_SELEXPR 
				(
				TOK_FUNCTIONSTAR 
						 count
				)
			)
		)
	)
)


上面语法树中,除括号外,每行对应一个  ASTNode,共13个节点,相互构成父子关系。

如:TOK_QUERY和TOK_INSERT为TOK_FROM的子节点;tt2为TOK_TABNAME的子节点。


二、语义分析

首先根据SQL类型创建对应的SemanticAnalyzer,对于这个sql,创建的就是 SemanticAnalyzer

1.分析语法树的每个节点,将后面要用到的相关数据保存到 Query Block 

2.查询表的元数据信息,顺便做些检查,如检查 table 是否 offline

3.创建 Operator

4.优化

5.生成 Task

这些步骤中,除去辅助工作外,最重要的是3、5部分。


3 根据语法树创建Operator

生成的 Operator 是个 DAG,每个节点是一个 Operator,每个 Operator 应该有指向所有子 Operator的指针,那么Operator的数据结构至少是这个样子:

class Operator<T extends OperatorDesc> implements Node {
  public List<Operator<? extends OperatorDesc>> getParentOperators() {
    return parentOperators;
  }
 public List<Operator<? extends OperatorDesc>> getChildOperators() {
    return childOperators;
  }
}
先看看 select count(*) from tableName 的Operator:

 
为了生成  operator tree,首先创建 operator tree 的 root operator,而root operator 总是 TableScanOperator

这个步骤会为所有from字句中的表创建一个 TableScanOperator,将 TableScanOperator 和表名的对应关系保存起来。

最先创建的总是 TableScanOperator,以后每创建一个Operator 都将当前Operator作为它的父Operator

ReduceSinkOperator和它的子Operator: GroupByOperator是同时创建的,它来帮助mapper输出结果,接着就由Reduce进行聚集操作。

所以创建Task时,如遇到处理的节点为ReduceSinkOperator,就直接根据它的子Operator 来生成Reduce Task.

可见这个SQL 中 TableScanOperator 的子Operator 只有一个 SelectOperator;FileSinkOperator  有一个父Operator: SelectOperator

在explain 中就可查看有哪些Operator:

STAGE DEPENDENCIES:
  Stage-1 is a root stage
  Stage-0 is a root stage


STAGE PLANS:
  Stage: Stage-1
    Map Reduce
      Alias -> Map Operator Tree:
        tt2 
          TableScan    //[1]
            alias: tt2
            Select Operator   //[2]
              Group By Operator   //[3]
                aggregations:
                      expr: count()
                bucketGroup: false
                mode: hash
                outputColumnNames: _col0
                Reduce Output Operator    //[4]
                  sort order: 
                  tag: -1
                  value expressions:
                        expr: _col0
                        type: bigint
      Reduce Operator Tree:
        Group By Operator   //[5]
          aggregations:
                expr: count(VALUE._col0)
          bucketGroup: false
          mode: mergepartial
          outputColumnNames: _col0
          Select Operator   //[6]
            expressions:
                  expr: _col0
                  type: bigint
            outputColumnNames: _col0
            File Output Operator   //[7]
              compressed: false
              GlobalTableId: 0
              table:
                  input format: org.apache.hadoop.mapred.TextInputFormat
                  output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat


  Stage: Stage-0
    Fetch Operator
      limit: -1


上面 explain 中的Operator 已标出。
TableScanOperator 不用说了,望文生义吧

SelectOperator 可进行列修剪,可减少 mapper  的输出数据量。

GroupByOperator 进行聚集操作,map 端的自然只能做部分聚集了。

FileSinkOperator 向文件系统写SQL结果文件。


5根据 Operator tree 创建 Task

首先创建一个Dispatcher,它保存了用RegExp标识的规则和相应的节点处理器NodeProcessor的映射集合,

这个集合决定了每一个节点 Operator的命运,它决定了处理它的NodeProcessor.

不同的规则的正则表达式可匹配对应的 Operator。

然后顶端( TableScanOperator)开始遍历这个DAG,为每个节点(Operator)找出一个规则 Rule。


TableScanOperator 最匹配的规则对应的 NodeProcessor 是 GenMRTableScan1,它会创建一个 MapRedTask

SelectOperator 找到的 Processor 为 GenMROperator,这个 Processor 仅仅保存了一下SelectOperator 和对应的 GenMRProcContext$GenMapRedCtx 的映射关系

ReduceSinkOperator 对应的 NodeProcessor: GenMRRedSink1

上面说过,以创建Task时,如遇到处理的节点为ReduceSinkOperator,就直接根据它的子Operator 来生成Reduce Task,这就是 GenMRRedSink1 来完成的。

具体来说,GenMRRedSink1 将这个 GroupByOperator 作为 reducer,把它存入当前任务中。当前任务就是刚才处理TableScanOperator时创建的 Task。


所有节点处理完后会生成所有的Task,此时 PhysicalOptimizer 会再优化一次。它遍历的其实还是个DAG,不过这时节点是 Task了。


至此,Task已经创建,可以着手创建Mapeduce Job 了。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值