大数据 - hive执行SQL语句基本流程- 源码02(转载)

目录导航
Driver类
编译的过程
代码入口以及过程
利用antlr将HiveQL转换成抽象语法树(AST)。
利用对应的SemanticAnalyzer类,将AST树转换成Map-reduce task。
Driver类
Driver类是hive最核心的类。Driver类是查询的起点,run()方法会先后调用compile()和execute()两个函数来完成查询,所以一个command的查询分为compile和execute两个阶段。

编译的过程

Compiler简介

解析器(Parser)–将查询字符串转换为解析树表示形式。
语义分析器(Semantic Analyser)-将解析树转换为内部查询表示形式,该表示形式基于块。
逻辑计划生成器(Logical Plan Generator)将内部查询表示形式转换为逻辑计划,该逻辑计划由运算符树组成。但是reduceSink等运算符是Hive专用的,将该计划转换为一系列map-reduce作业。
查询计划生成器(Query Plan Generator)将逻辑计划转换为一系列的map-reduce任务。 查询计划计划被序列化并写入文件。
代码入口以及过程
Driver.run()方法调用Driver.runInternal()方法,首先该方法中会判断SQL是否经过编译,若未进行编译,则会调用compileInternal之后调用compile方法进行编译。

利用antlr将HiveQL转换成抽象语法树(AST)。
首先使用antlr工具将srcqlsrcjavaorgapachehadoophiveqlparsehive.g编译成以下几个文件:HiveParser.java, Hive.tokens, Hive__.g, HiveLexer.java。
HiveLexer.java和HiveParser.java分别是词法和语法分析类文件,Hive__.g是HiveLexer.java对应的词法分析规范,Hive.tokens定义了词法分析后所有的token。
然后沿着“Driver.compile()->ParseDriver.parse(command, ctx)->HiveParserX.statement()->antlr中的API”这个调用关系把输入的HiveQL转化成ASTNode类型的语法树。HiveParserX是由antlr生成的HiveParser类的子类。
//将SQL语句转化为AST树
ParseDriver pd = new ParseDriver();
ASTNode tree = pd.parse(command, ctx);
tree = ParseUtils.findRootNonNullToken(tree);
perfLogger.PerfLogEnd(CLASS_NAME, PerfLogger.PARSE);
1
2
3
4
5
利用对应的SemanticAnalyzer类,将AST树转换成Map-reduce task。
这部分会用到BaseSemanticAnalyzer.analyze,大致流程是先通过anticAnalyzerFactory.get(queryState, tree),初始化BaseSemanticAnalyzer对象,并且确定了该SQL的类型。SQL的类型以及使用了哪些算子都在org/apache/hadoop/hive/ql/parse/HiveParser.g语法文件中枚举出来了。
然后会通过sem.analyze(tree, ctx)调用analyzeInternal

public void analyze(ASTNode ast, Context ctx) throws SemanticException {
initCtx(ctx);
init(true);
analyzeInternal(ast);
}
1
2
3
4
5
以查询语句为例。进入进入的子类是SemanticAnalyzer. analyzeInternal()
整体逻辑为:

doPhase1():将sql语句中涉及到的各种信息存储起来,存到QB中去,留着后面用。
if (!doPhase1(child, qb, ctx_1, plannerCtx)) {
// if phase1Result false return
return false;
}
1
2
3
4
getMetaData():获取元数据信息,主要是sql中涉及到的 表 和 元数据 的关联
public void getMetaData(QB qb, boolean enableMaterialization) throws SemanticException {
try {
if (enableMaterialization) {
getMaterializationMetadata(qb);
}
getMetaData(qb, null);
} catch (HiveException e) {
// Has to use full name to make sure it does not conflict with
// org.apache.commons.lang.StringUtils
LOG.error(org.apache.hadoop.util.StringUtils.stringifyException(e));
if (e instanceof SemanticException) {
throw (SemanticException)e;
}
throw new SemanticException(e.getMessage(), e);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
genPlan():生成operator tree/DAG
Operator sinkOp = genOPTree(ast, plannerCtx);

Operator genOPTree(ASTNode ast, PlannerContext plannerCtx) throws SemanticException {
return genPlan(qb);
}

private Operator genPlan(QB parent, QBExpr qbexpr) throws SemanticException {
if (qbexpr.getOpcode() == QBExpr.Opcode.NULLOP) {
boolean skipAmbiguityCheck = viewSelect == null && parent.isTopLevelSelectStarQuery();
return genPlan(qbexpr.getQB(), skipAmbiguityCheck);
}
if (qbexpr.getOpcode() == QBExpr.Opcode.UNION) {
Operator qbexpr1Ops = genPlan(parent, qbexpr.getQBExpr1());
Operator qbexpr2Ops = genPlan(parent, qbexpr.getQBExpr2());

  return genUnionPlan(qbexpr.getAlias(), qbexpr.getQBExpr1().getAlias(),
      qbexpr1Ops, qbexpr.getQBExpr2().getAlias(), qbexpr2Ops);
}
return null;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
optimize():优化,对operator tree/DAG 进行一些优化操作,例如列剪枝等(目前只能做rule-based optimize,不能做cost-based optimize)
//逻辑优化
pCtx = optm.optimize();//fetchTask在逻辑执行计划最后一步生成
1
2
getFetchTask()开始生成物理执行计划
//fetchTask是物理执行计划的开始
FetchTask origFetchTask = pCtx.getFetchTask();

//不同引擎生成不同物理计划
compiler.compile(pCtx, rootTasks, inputs, outputs);


//生成物理执行计划
generateTaskTree(rootTasks, pCtx, mvTask, inputs, outputs);


//物理优化
optimizeTaskPlan(rootTasks, pCtx, ctx);

1
2
3
4
5
6
7
8
9
10
11
12
13
整体的编译流程大概如此,下篇谈一下执行的过程。
本文采用hive2.1.1源码为参考。

原文链接:https://blog.csdn.net/weixin_45518155/article/details/107449410?utm_medium=distribute.pc_feed.none-task-blog-personrec_tag-2.nonecase&depth_1-utm_source=distribute.pc_feed.none-task-blog-personrec_tag-2.nonecase&request_id=5f1ff13c9cc79f6252ce3e01

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值