陈略

好记性不如烂笔头。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Hive学习笔记 之 Hive运行流程简析3

版权声明:本文为原创文章,欢迎转载,请注明出处。

HiveSession

续上篇的流程。

客户端的任何调用,基本流程都是如。在SessionManager建立好连接后,会将其管理在一个SessionManager对象的一个Map中handleToSession,以SessionHandle为key,并将key返回给客户端,后续客户端在这个会话中的请求,都会携带这个sessionHandle,作为寻找Session的唯一ID。

Operation & CommandProcessor

而执行SQL语句是就是Hive客户端使用过程中最基本的场景和最重要的场景了。从JDBC的HiveStatement类开始执行,Beeline -> JDBC ->ThriftCLIService -> CLIService -> HiveSessionImpl从上面的一串类中摸爬滚打过来,执行一系列长得就像executeStatement的方法,最后调用了executeStatementInternal方法,新建一个ExecuteStatementOperation的对象,新建该对象的过程中,会识别Hive自身的命令,或者是SQL的命令,并生成不同的Processor作为对象成员保存在Operation中。从下面的类图可以看出,该对象包括了Hive两种命令的处理,一种是SQLOperation,内包含一个Driver类型的Processor,其他是Hive命令,通过一个命令工厂,来返回对应的Processor。

Operation (org.apache.hive.service.cli.operation)
	ExecuteStatementOperation (org.apache.hive.service.cli.operation)
		HiveCommandOperation (org.apache.hive.service.cli.operation)
		SQLOperation (org.apache.hive.service.cli.operation)
CommandProcessor (org.apache.hadoop.hive.ql.processors)
	AddResourceProcessor (org.apache.hadoop.hive.ql.processors)
	CompileProcessor (org.apache.hadoop.hive.ql.processors)
	CryptoProcessor (org.apache.hadoop.hive.ql.processors)
	DeleteResourceProcessor (org.apache.hadoop.hive.ql.processors)
	DfsProcessor (org.apache.hadoop.hive.ql.processors)
	Driver (org.apache.hadoop.hive.ql)
		HCatDriver (org.apache.hive.hcatalog.cli)
	ListResourceProcessor (org.apache.hadoop.hive.ql.processors)
	ReloadProcessor (org.apache.hadoop.hive.ql.processors)
	ResetProcessor (org.apache.hadoop.hive.ql.processors)
	SetProcessor (org.apache.hadoop.hive.ql.processors)

这部分的核心代码位于ExecuteStatementOperation类中。节选如下。

  public static ExecuteStatementOperation newExecuteStatementOperation(
      HiveSession parentSession, String statement, Map<String, String> confOverlay, boolean runAsync)
          throws HiveSQLException {
    String[] tokens = statement.trim().split("\\s+");
    CommandProcessor processor = null;
    try {
      processor = CommandProcessorFactory.getForHiveCommand(tokens, parentSession.getHiveConf());
    } catch (SQLException e) {
      throw new HiveSQLException(e.getMessage(), e.getSQLState(), e);
    }
    if (processor == null) {
      return new SQLOperation(parentSession, statement, confOverlay, runAsync);
    }
    return new HiveCommandOperation(parentSession, statement, processor, confOverlay);
  }

SQLOperation & Driver

从上一节的类图中,可以清晰看到这俩哥就是上一节两位哥的派生类,但是为何要单独列出来,废话,肯定是因为他们很重要啊。现在我们已经清楚了这俩哥的结构和来龙去脉,那么是时候进来探探,他们到底干了些啥了。

HiveSessionImpl中,获取到这两个货以后,说明我们是在执行一条SQL语句而不是别的什么鬼,获取到他们之后,就简单得将他们run起来试试。

SQLOperation从父类的run方法进来。做两件事:prepare和runQuery。听起来so easy的事情。。但是,进入之后将会豁然开朗,别有洞天。

Driver.compile

所谓豁然开朗,一定是从一段极其压抑的过程经过,然后大开眼界的这种。so,一路从run方法进来,并没有什么有意思之处,直到碰见compile,我说它是Hive的心脏,完全不够准确,它分明是Hive的大脑!!

它将负责SQL语句的词法句法语法解析、查询操作符生成与优化、执行任务的生成与优化,只有在这个大脑情绪稳定、心情舒畅的时候,才能正确地指导Hive在接受到一条SQL语句后所完成的活动。

同时,从Hive的代码工程上来看,前面的流程都分别属于beeline、jdbc还有Service,而从这里开始,代码的目录被成为ql,即Query Language,工程的名字被称之为exec,即Execute。那么,这里,才是,真正为Hive出谋划策的地方。

开场白说得有点多。该拉回现场了。

首先是SQL的词法和句法解析,这里Hive引入了第三方组件antlr来干这事,官网。相当于Hive的小半个大脑是别人给的。antlr是个语言解析器,其用户按照自定义的规则编写.g文件,解析器将基于.g文件中定义的规则解析传入的语句,生成抽象语法树,简称AST。这个过程是一个非常数学的过程,如果觉得时间够多,脑细胞够用,可以考虑研究一下.g文件的写法以及生成的过程,我是没这耐心和能力的,因此先行略过,直接从AST开始。

      perfLogger.PerfLogBegin(CLASS_NAME, PerfLogger.PARSE);
      ParseDriver pd = new ParseDriver();
      ASTNode tree = pd.parse(command, ctx);
      tree = ParseUtils.findRootNonNullToken(tree);
      perfLogger.PerfLogEnd(CLASS_NAME, PerfLogger.PARSE);

compile方法的上面代码段出来后,tree变量即为我要的AST。那么下面将循序渐进,用两条SQL语句来说明接下来Driver拿这个AST动了什么手脚。

第一条,最简单的建表语句:

create table t1(id int, name string) 
row format delimited fields terminated by ',' 
stored as textfile;

其对应的AST如下:

 ABSTRACT SYNTAX TREE:                                                     
                                                                           
 TOK_CREATETABLE                                                           
    TOK_TABNAME                                                                                                                  
       t1                                                                   
    TOK_LIKETABLE                                                           
    TOK_TABCOLLIST                                                          
       TOK_TABCOL                                                           
          id                                                                
          TOK_INT                                                           
       TOK_TABCOL                                                           
          name                                                              
          TOK_STRING                                                        
    TOK_TABLEROWFORMAT                                                      
       TOK_SERDEPROPS                                                       
          TOK_TABLEROWFORMATFIELD                                           
             ','                                                            
    TOK_FILEFORMAT_GENERIC                                                  
       textfile    

其实AST每个节点的名称上,基本就可以看明白它代表的意义了。接下来的问题是,Hive是怎么把抽象~语法树真正用起来,达成我们想要的效果的呢。

这时候,就轮到语义解析了。

SemanticAnalyzer

首先,我们根据AST的根节点,从工厂SemanticAnalyzerFactory中获取到对应的语义解析类对象。建表的话,获取到的是缺省解析器SemanticAnalyzer

未完待续

posted on 2016-01-20 23:19  陈略  阅读(1188)  评论(0编辑  收藏  举报