前言
本文隶属于专栏《大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!
本专栏目录结构和参考文献请见大数据技术体系
正文
本文介绍 Apache Hive 如何将 SQL 转化为 MapReduce 任务,整个编译过程可以分为六个阶段:
- 对 SQL 进行词法、语法解析,将SQL 转化为 AST Tree(抽象语法树)。
- 遍历 AST Tree, 进一步抽象和结构化,将 AST Tree 转化为 SQL 的基本组成单元 QueryBlock。
- 遍历 QueryBlock,转化为 Operator Tree(执行操作树)。
- 通过逻辑层优化器进行 Operator Tree 变换。
- 遍历Operator Tree,翻译为 MapReduce 任务。
- 通过物理层优化器进行 MapReduce 任务的变换,生成最终的执行计划。
为便于理解,用一个简单的 SQL 语句进行讲解。我们查询某表中 10 月 1 日的数据:
select * from db.table where time = 20191001
这条 SQL 会经历以下的编译过程。
1. 根据 Antlr 定义的语法规则,对SQL 进行词法、语法解析,转化为如下 AST Tree:
ABSTRACT SYNTAX TREE:
TOK_OUERY
TOK_FROM
TOK_TABREF
TOK_TABNAME
db
table
TOK_INSERT
TOK_DESTINATION
TOK_DIR
TOK_TMP_FILE
TOK_SELECT
TOK_SELEXPR
TOK_ALLCOLREF
TOK_WHERE
=
TOK_TABLE_OR_COL
time
20191001
2. 遍历 AST Tree,抽象出查询的基本组成单元 Query Block
AST Tree 生成后仍然非常复杂,不便于翻译为 MapReduce 程序,需要进行进一步抽象和结构化,转化为 QueryBlock。
QueryBlock 是 SQL 最基本的组成单元,包括输人源、计算过程和输出。
QueryBlock 以递归的方式生成,先序遍历 AST Tree,遇到不同的 Token 节点,保存到相应的属性中,包含以下几个过程。
- TOK_ QUERY:创建 Query Block 对象,循环递归子节点。
- TOK_FROM:将表名语法部分保存到 QueryBlock 对象的 aliasToTabs 等属性中。
- TOK_ INSERT:循环递归子节点。
- TOK_DESTINATION:将输出目标的语法部分保存在 QBParseInfo 对象的nameToDest 属性中。
- TOK_ SELECT:分别将查询表达式的语法部分保存在 destToSelExpr、destToAggregationExprs、 destToDistinctFuncExprs 三个属性中。
- TOK_ WHERE:将 Where 部分的语法保存 在QBParselnfo对象的destTo WhereExpr属性中。
3. 遍历 QueryBlock,转换为 Operator Tree
Hive 最终生成的 MapReduce 任务、Map 阶段和 Reduce 阶段均由 Operator Tree 组成。
逻辑操作符(Operator)是在 Map 阶段或者 Reduce 阶段完成单一特定的操作。
基本的操作符包括 TableScanOperator、 SelectOperator、 Filter- Operator、 GroupBy Operator、JoinOperator、 ReduceSinkOperator
4. 通过逻辑层优化器对 Operator Tree 进行优化操作。
逻辑层优化器通过变换 Operator Tree 和合并操作符來达到减少 MapReduce Job和减少 Shuffle数据量的目的。
5. 遍历 OperatorTree,翻泽为 MapReduce 任务,分为下面几个的阶段:
- 对输出表生成 MoveTask
- 从 OperatorTree 的其中一个根节点向下深度优先遍历。
- ReduceSinkOperator 标示 Map/Reduce 的界限、多个 Job 间的界限。
- 遍历其他根书点,如果碰到 JoinOperator 则合并 MapReduceTask.
- 生成 StatTask 来更新元数据。
- 切断 Map 与 Reduce 间的 Operator的关系。
6. 通过物理层优化器对 MapReduce 任务进行优化,生成最终的执行计划。