Hivesql ->mapreduce 简单的可以分为六个阶段:
1、SQL词法,语法解析生成抽象语法树AST Tree Antrl定义了SQL语法规则,完成SQL词法、语法解析,将SQL转化为抽象语法树AST Tree,树上的每个节点就是一个ASTNode;
2、遍历AST Tree,抽象出查询的基本组成单元QueryBlock QueryBlock就是一个子查询
Select * from (select * from b) a;
QueryBlock1:select * from b;
QueryBlock2:select * from a;
3、遍历QueryBlock,翻译成执行操作树OperatorTree
4、逻辑层优化器进行OperatorTree变化,合并不必要的ReduceSinkOperator,减少shuffle数据量
5、遍历OperatorTree,翻译成MapReduce任务(物理执行计划)
6、物理层优化器进行MapReduce任务的变换,生成最终的执行计划
下面对hive-2.3.9源码进行详细的分析:
CliDriver类:
685行:main()
687行:run()
694行:!oproc.process_stage1(args) 解析hiveconf参数,如日志级别;
719行:!oproc.process_stage2(ss) 解析hive -i -f -e -S -H -hivevar等 如:hive -e "select * from student";
760行:executeDriver(ss,conf,oproc);
804行:setupConsoleReader(); 初始化从console读取用户编辑的sql命令等;
879行:setupCmdHistory(); 设置hql命令历史记录相关操作;
813行:while()循环不停的读取 命令 执行
822行:processLine() 解析处理SQL
349行 :processLine()
353行:ctrl+c处理;
388行:切分出每一个单独的sql;
403行:processCmd(command) 执行每一条sql;
117行:processCmd()
129行:分支处理各种sql;
184行:处理正真的sql:"select …" 这样的
215行:processLocalCmd()
233行:qp.run(cmd) 执行sql;
245行:输出表头;
254行:输出数据;
279行:数据查询时间和行数信息;
Driver类中run() 执行查询语句的方法
1235行:run()
1237行:runInternal() 该方法做两件事:1.编译:sql->物理执行计划;2、执行:LauchTask();
1407行:runInternal()
1457行:compileInternal(command,true); 编译
1317行:compile(command,true,deferClose);编译,做了三件事
468行:ASTNodetree=ParseUtils.parse(command,ctx); 将hql转译成ASTNode抽象语法树;
506行:sem.analyze(tree,ctx);sem(SemacticAnalyzer(寓意分析器))将ASTNode转化成TaskTree (物理执行计划)
531行:plan=newQueryPlan(queryStr,sem,perfLogger.getStartTime(PerfLogger.DRIVER_RUN),queryId,queryState.getHiveOperation(),schema); 把TaskTree生成一个QueryPlan;
1526行:execute(true); 执行
最重要的一个类:SemanticAnalyzer类:
11128行:analyzeInternal(ASTNodeast,PlannerContextplannerCtx)
抽象语法树 生成 解析树,AST Tree 仍然很复杂,不够结构化,不方便直接翻译成为MapReduce程序;AST Tree转化为QueryBlock就是将sql进一步抽象和结构化;QueryBlock是一条sql的最基本组成单元,包含三部分:输入源/计算过程/输出;简单来说:QueryBlock就是一个子查询;在这个环节中,会有和元数据库的交互;
// 1. Generate Resolved Parse tree from syntax tree 将AST Tree转化成解析树,先将AST Tree -> QueryBlock -> 解析树胡
// 2. Gen OP Tree from resolved Parse Tree 将解析树转化成Operator Tree
// 3. Deduce Resultset Schema 推导结果模式,这里面有cbo优化,在多表join的时间自动的选择最有的join方式
// 4. Generate Parse Context for Optimizer & Physical compiler 生成上下文件context对象
// 5. Take care of view creation 处理试图操作
// 6. Generate table access stats if required 生成表的表访问信息
// 7. Perform Logical optimization 添加各种优化器并依次执行逻辑优化
// 8. Generate column access stats if required - wait until
column pruning takes place during optimization 可能的情况下,做列裁剪
// 9. Optimize Physical op tree &
Translate to target execution engine (MR,TEZ..) 优化Operator Tree生成物理执行计划并指定执行引擎
// 10. put accessed columns to readEntity 封装查询的列到readEntity
// 11. if desired check we're not going over partition scan limits 分区扫描的时候分区限制
大致流程图如下: