上一篇:Hive 源码系列二:Driver主要分析 Hive 的客户端如何获取用户的执行 SQL,并维护整个客户端环境;本节作为 Hive 的 SQL 是如何执行大类的第一部分:SQL -> AST,在计算机科学中,抽象语法树(Abstract Syntax Tree,AST)是源代码语法结构的一种抽象表示,它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。让我们看一下 Hive 的 SQL 是如何转换成 AST 的
从上节的tree = ParseUtils.parse(command, ctx);
开始,Hive 使用 Antlr 框架将 SQL 转换成 AST,因此具体是如何转换的是需要研究 Antlr 框架,本节从宏观上过一遍。
HiveLexerX lexer = new HiveLexerX(new ANTLRNoCaseStringStream(command));
// 词法 语法解析 获得 token
TokenRewriteStream tokens = new TokenRewriteStream(lexer);
将 SQL 封装成 HiveLexerX 类,并通过这个类将 SQL 转换成 tokens,token 的本质就是 SQL 的一个单元,如:
select * from a;
上述 SQL 对应的 tokens 就是
tokens[0] = "select"
tokens[1] = " "
tokens[2] = "*"
tokens[3] = " "
tokens[4] = "from"
tokens[5] = " "
tokens[6] = "a"
tokens[7] = ";"
继续
// token 获取 解析器
HiveParser parser = new HiveParser(tokens);
基于 tokens 获取 HiveParser 类,这个类就是 Antlr 框架生成的,Antlr 的使用需要指定一个语法文件(xxx.g),可以简单的理解为 xxx.g 记录了 Hive SQL 所有语法关键字组成一个 K-V 映射,根据 tokens 获取 AST 组成单元,即将 SQL -> tokens -> AST,Hive 所使用的的语法文件在
org/apache/hadoop/hive/ql/parse/xxx.g
这里用到的是 HiveLexer.g、HiveParser.g 文件大致内容如下
基于 HiveParser 来做真正的语法解析
// todo 解析 SQL
r = parser.statement();
// todo 获取 AST
ASTNode tree = (ASTNode) r.getTree();
到这里就将 SQL 转换成一个 AST,下面来一个真实的 SQL
insert overwrite table advance.jointable
select b.id, b.t, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from advance.smalltable s
join advance.bigtable b
on s.id = b.id;
SQL -> AST
tok_query
+tok_from
+tok_join
+tok_tabref
+tok_tabname advance smalltable s
+tok_tabref
+tok_tabname advance bigtable b
+ =
+.
+tok_table_or_col s id
+.
+tok_table_or_col b id
+tok_insert
+tok_destination
+tok_tab
+tok_tabname advance jointable
+tok_select
+tok_selexpr
+.
+tok_table_or_col b id
+tok_selexpr
+.
+tok_table_or_col b t
+tok_selexpr
+.
+tok_table_or_col b uid
+tok_selexpr
+.
+tok_table_or_col b keyword
+tok_selexpr
+.
+tok_table_or_col b url_rank
+tok_selexpr
+.
+tok_table_or_col b click_num
+tok_selexpr
+.
+tok_table_or_col b click_url
从这种结构的 AST 大致是可以看出原来的 SQL,并且看出 SQL 是按什么顺序执行的,而 Hive 也是基于 AST 进行之后的词法语法分析,将 AST 进一步转换成解析树(Query Block,QB)在这里替换元数据,再基于 QB 做进一步操作如生成OP Tree 即逻辑执行计划(explain出来的东西)、优化逻辑执行计划、生成Task Tree 即物理执行计划等等…感兴趣的可以继续关注