转载:http://www.cnblogs.com/yaojingang/p/5446310.html

在了解了MapReduce实现SQL基本操作之后,我们来看看Hive是如何将SQL转化为MapReduce任务的,整个编译过程分为六个阶段:

  1. Antlr定义SQL的语法规则,完成SQL词法,语法解析,将SQL转化为抽象语法树AST Tree
  2. 遍历AST Tree,抽象出查询的基本组成单元QueryBlock
  3. 遍历QueryBlock,翻译为执行操作树OperatorTree
  4. 逻辑层优化器进行OperatorTree变换,合并不必要的ReduceSinkOperator,减少shuffle数据量
  5. 遍历OperatorTree,翻译为MapReduce任务
  6. 物理层优化器进行MapReduce任务的变换,生成最终的执行计划

下面分别对这六个阶段进行介绍

Phase1 - SQL词法,语法解析

Antlr

Hive使用Antlr实现SQL的词法和语法解析。Antlr是一种语言识别的工具,可以用来构造领域语言。
这里不详细介绍Antlr,只需要了解使用Antlr构造特定的语言只需要编写一个语法文件,定义词法和语法替换规则即可,Antlr完成了词法分析、语法分析、语义分析、中间代码生成的过程。

Hive中语法规则的定义文件在0.10版本以前是Hive.g一个文件,随着语法规则越来越复杂,由语法规则生成的Java解析类可能超过Java类文 件的最大上限,0.11版本将Hive.g拆成了5个文件,词法规则HiveLexer.g和语法规则的4个文件 SelectClauseParser.g,FromClauseParser.g,IdentifiersParser.g,HiveParser.g。

抽象语法树AST Tree

经过词法和语法解析后,如果需要对表达式做进一步的处理,使用 Antlr 的抽象语法树语法Abstract Syntax Tree,在语法分析的同时将输入语句转换成抽象语法树,后续在遍历语法树时完成进一步的处理。

下面的一段语法是Hive SQL中SelectStatement的语法规则,从中可以看出,SelectStatement包含select, from, where, groupby, having, orderby等子句。
(在下面的语法规则中,箭头表示对于原语句的改写,改写后会加入一些特殊词标示特定语法,比如TOK_QUERY标示一个查询块)

Phase2 - SQL基本组成单元QueryBlock

AST Tree仍然非常复杂,不够结构化,不方便直接翻译为MapReduce程序,AST Tree转化为QueryBlock就是将SQL进一部抽象和结构化。

QueryBlock

QueryBlock是一条SQL最基本的组成单元,包括三个部分:输入源,计算过程,输出。简单来讲一个QueryBlock就是一个子查询。

下图为Hive中QueryBlock相关对象的类图,解释图中几个重要的属性

  • QB#aliasToSubq(表示QB类的aliasToSubq属性)保存子查询的QB对象,aliasToSubq key值是子查询的别名
  • QB#qbp 即QBParseInfo保存一个基本SQL单元中的给个操作部分的AST Tree结构,QBParseInfo#nameToDest这个HashMap保存查询单元的输出,key的形式是inclause-i(由于Hive 支持Multi Insert语句,所以可能有多个输出),value是对应的ASTNode节点,即TOK_DESTINATION节点。类QBParseInfo其余 HashMap属性分别保存输出和各个操作的ASTNode节点的对应关系。
  • QBParseInfo#JoinExpr保存TOK_JOIN节点。QB#QBJoinTree是对Join语法树的结构化。
  • QB#qbm保存每个输入表的元信息,比如表在HDFS上的路径,保存表数据的文件格式等。
  • QBExpr这个对象是为了表示Union操作。

AST Tree生成QueryBlock

AST Tree生成QueryBlock的过程是一个递归的过程,先序遍历AST Tree,遇到不同的Token节点,保存到相应的属性中,主要包含以下几个过程

  • TOK_QUERY => 创建QB对象,循环递归子节点
  • TOK_FROM => 将表名语法部分保存到QB对象的TOK_INSERT => 循环递归子节点
  • TOK_DESTINATION => 将输出目标的语法部分保存在QBParseInfo对象的nameToDest属性中
  • TOK_SELECT => 分别将查询表达式的语法部分保存在destToAggregationExprsTOK_WHERE => 将Where部分的语法保存在QBParseInfo对象的destToWhereExpr属性中

最终样例SQL生成两个QB对象,QB对象的关系如下,QB1是外层查询,QB2是子查询

QB1 \ QB2

Phase3 - 逻辑操作符Operator

Operator

Hive最终生成的MapReduce任务,Map阶段和Reduce阶段均由OperatorTree组成。逻辑操作符,就是在Map阶段或者Reduce阶段完成单一特定的操作。

基本的操作符包括TableScanOperator,SelectOperator,FilterOperator,JoinOperator,GroupByOperator,ReduceSinkOperator

从名字就能猜出各个操作符完成的功能,TableScanOperator从MapReduce框架的Map接口原始输入表的数据,控制扫描表的数据行数,标记是从原表中取数据。JoinOperator完成Join操作。FilterOperator完成过滤操作

ReduceSinkOperator将Map端的字段组合序列化为Reduce Key/value, Partition Key,只可能出现在Map阶段,同时也标志着Hive生成的MapReduce程序中Map阶段的结束。

Phase4 - 逻辑层优化器

大部分逻辑层优化器通过变换OperatorTree,合并操作符,达到减少MapReduce Job,减少shuffle数据量的目的。

② MapJoinProcessor

② GroupByOptimizer

① PredicatePushDown

ColumnPruner

名称

作用

② SimpleFetchOptimizer

优化没有GroupBy表达式的聚合查询

MapJoin,需要SQL中提供hint,0.11版本已不用

② BucketMapJoinOptimizer

BucketMapJoin

Map端聚合

① ReduceSinkDeDuplication

合并线性的OperatorTree中partition/sort key相同的reduce

谓词前置

① CorrelationOptimizer

利用查询中的相关性,合并有相关性的Job,HIVE-2206

字段剪枝

表格中①的优化器均是一个Job干尽可能多的事情/合并。②的都是减少shuffle数据量,甚至不做Reduce。

CorrelationOptimizer优化器非常复杂,都能利用查询中的相关性,合并有相关性的Job,参考 Hive Correlation Optimizer

对于样例SQL,有两个优化器对其进行优化。下面分别介绍这两个优化器的作用,并补充一个优化器ReduceSinkDeDuplication的作用.

Phase5 -  OperatorTree生成MapReduce Job的过程

OperatorTree转化为MapReduce Job的过程分为下面几个阶段

  1. 对输出表生成MoveTask
  2. 从OperatorTree的其中一个根节点向下深度优先遍历
  3. ReduceSinkOperator标示Map/Reduce的界限,多个Job间的界限
  4. 遍历其他根节点,遇过碰到JoinOperator合并MapReduceTask
  5. 生成StatTask更新元数据
  6. 剪断Map与Reduce间的Operator的关系

Phase6 - 物理层优化器

这里不详细介绍每个优化器的原理,单独介绍一下MapJoin的优化器

SortMergeJoinResolver

CommonJoinResolver + MapJoinResolver

名称

作用

Vectorizer

HIVE-4160,将在0.13中发布

与bucket配合,类似于归并排序

SamplingOptimizer

并行order by优化器,在0.12中发布

MapJoin优化器

MapJoin原理

MapJoin简单说就是在Map阶段将小表读入内存,顺序扫描大表完成Join。

上图是Hive MapJoin的原理图,出自Facebook工程师Liyin Tang的一篇介绍Join优化的slice,从图中可以看出MapJoin分为两个阶段:

  1. 通过MapReduce Local Task,将小表读入内存,生成HashTableFiles上传至Distributed Cache中,这里会对HashTableFiles进行压缩。

  2. MapReduce Job在Map阶段,每个Mapper从Distributed Cache读取HashTableFiles到内存中,顺序扫描大表,在Map阶段直接进行Join,将数据传递给下一个MapReduce任务。

如果Join的两张表一张表是临时表,就会生成一个ConditionalTask,在运行期间判断是否使用MapJoin

CommonJoinResolver优化器

CommonJoinResolver优化器就是将CommonJoin转化为MapJoin,转化过程如下

  1. 深度优先遍历Task Tree
  2. 找到JoinOperator,判断左右表数据量大小
  3. 对与小表 + 大表 => MapJoinTask,对于小/大表 + 中间表 => ConditionalTask

遍历上一个阶段生成的MapReduce任务,发现JOIN[8]中有一张表为临时表,先对Stage-2进行深度拷贝(由于需要保留原始执行计划为Backup
Plan,所以这里将执行计划拷贝了一份),生成一个MapJoinOperator替代JoinOperator,然后生成一个MapReduceLocalWork读取小表生成HashTableFiles上传至DistributedCache中。

Operator在Map Reduce阶段之间的数据传递都是一个流式的过程。每一个Operator对一行数据完成操作后之后将数据传递给childOperator计算。

Operator类的主要属性和方法如下

    • RowSchema表示Operator的输出字段
    • InputObjInspector outputObjInspector解析输入和输出字段
    • processOp接收父Operator传递的数据,forward将处理好的数据传递给子Operator处理
    • Hive每一行数据经过一个Operator处理之后,会对字段重新编号,colExprMap记录每个表达式经过当前Operator处理前后的名称对应关系,在下一个阶段逻辑优化阶段用来回溯字段名
    • 由 于Hive的MapReduce程序是一个动态的程序,即不确定一个MapReduce Job会进行什么运算,可能是Join,也可能是GroupBy,所以Operator将所有运行时需要的参数保存在OperatorDesc 中,OperatorDesc在提交任务前序列化到HDFS上,在MapReduce任务执行前从HDFS读取并反序列化。Map阶段 OperatorTree在HDFS上的位置在Job.getConf(“hive.exec.plan”)
      + “/map.xml”
    • QueryBlock生成Operator Tree

      QueryBlock生成Operator Tree就是遍历上一个过程中生成的QB和QBParseInfo对象的保存语法的属性,包含如下几个步骤:

      • QB#aliasToSubq => 有子查询,递归调用
      • QB#aliasToTabs => TableScanOperator
      • QBParseInfo#joinExpr => QBJoinTree => ReduceSinkOperator + JoinOperator
      • QBParseInfo#destToWhereExpr => FilterOperator
      • QBParseInfo#destToGroupby => ReduceSinkOperator + GroupByOperator
      • QBParseInfo#destToOrderby => ReduceSinkOperator + ExtractOperator

      由于Join/GroupBy/OrderBy均需要在Reduce阶段完成,所以在生成相应操作的Operator之前都会先生成一个ReduceSinkOperator,将字段组合并序列化为Reduce Key/value, Partition Key

      接下来详细分析样例SQL生成OperatorTree的过程

      先序遍历上一个阶段生成的QB对象

SQL转化为MapReduce的过程的更多相关文章

  1. Hive将SQL转化为MapReduce的过程

    Hive将SQL转化为MapReduce的过程: Antlr定义SQL的语法规则,完成SQL词法,语法解析,将SQL转化为抽象语法树AST Tree 遍历AST Tree,抽象出查询的基本组成单元Qu ...

  2. hive--构建于hadoop之上、让你像写SQL一样编写MapReduce程序

    hive介绍 什么是hive? hive:由Facebook开源用于解决海量结构化日志的数据统计 hive是基于hadoop的一个数据仓库工具,可以将结构化的数据映射为数据库的一张表,并提供类SQL查 ...

  3. 从HiveQL到MapReduce job过程简析

    一.简述 HiveQL是一种声明式语言,用户提交查询,而Hive会将其转换成MapReduce job,如下图.一般来说大部分时间可以无视这个执行过程的内部逻辑,但是如果能了解这些底层实现细节,在调优 ...

  4. YARN(MapReduce 2)运行MapReduce的过程-源码分析

    这是我的分析,当然查阅书籍和网络.如有什么不对的,请各位批评指正.以下的类有的并不完全,只列出重要的方法. 如要转载,请注上作者以及出处. 一.源码阅读环境 需要安装jdk1.7.0版本及其以上版本, ...

  5. Hadoop MapReduce执行过程详解(带hadoop例子)

    https://my.oschina.net/itblog/blog/275294 摘要: 本文通过一个例子,详细介绍Hadoop 的 MapReduce过程. 分析MapReduce执行过程 Map ...

  6. MapReduce Shuffle过程

    MapReduce Shuffle 过程详解 一.MapReduce Shuffle过程 1. Map Shuffle过程 2. Reduce Shuffle过程 二.Map Shuffle过程 1. ...

  7. 64位 SQL Server2008链接访问Oracle 过程汇总解决方法记录

    64位 SQL Server2008链接访问Oracle 过程汇总解决方法记录 经过几天不停的网上找资料,实验,终于联通了. 环境:系统:win 2008 ,SqlServer2008 R2, 连接O ...

  8. MapReduce运行过程以及原理

    1.map和reduce MapReduce任务过程分为两个处理阶段:map阶段和reduce阶段.每个节点都以键值对作为输入和输出,其类型由程序员来选择.程序员还需要编写两个函数:map函数和red ...

  9. 分析MapReduce执行过程

    分析MapReduce执行过程 MapReduce运行的时候,会通过Mapper运行的任务读取HDFS中的数据文件,然后调用自己的方法,处理数据,最后输出. Reducer任务会接收Mapper任务输 ...

随机推荐

  1. VB.NET版机房收费系统---异常处理

    异常处理,英文名为Exceptional Handling, 那时年少,还记得那年一起学习过的VB6.0的时候,常常使用ONError的错误语句.与传统VB6.0中的OnError语句相比.NET平台 ...

  2. Ionic APP-Web SPA开发进阶(二)Ionic进阶之路由去哪了

    Ionic进阶之路由去哪了 项目需求 在查看药品时,从药品列表中可以通过点击药品列表获取某一药品详情.提交订单时,同样可以查看药品详情.两种情形下,从药品详情返回后,应分别返回至原来的页面.如下图所示 ...

  3. Android 5.0 SEAndroid下如何获得对一个内核节点的访问权限

    -9]* u:object_r:tty_device:s0 # We add here /dev/wf_bt              u:object_r:wf_bt_device:s0 wf_bt ...

  4. C语言实现ifconfig获取网卡接收和发送流量统计

    在Windows下我们可以利用ipconfig命令获取网卡的相关信息,在Linux下命令是ifconfig 我们可以获取的信息更为丰富,其中包括网卡接收和发送的流量,用C语言实现这个命令并不是一件简单 ...

  5. 命令行界面的C/S聊天室应用 (Socket多线程实现)

    命令行界面即在Eclipe控制台输入数据. 服务器端包含多个线程,每个Socket对应一条线程,该线程负责读取对应输入流的数据(从客户端发送过来的数据),并将读到的数据向每个Socket输出流发送一遍 ...

  6. 使用Multiplayer Networking做一个简单的多人游戏例子-2/3(Unity3D开发之二十六)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/51007512 ...

  7. 【Java编程】随机数的不重复选择

    随机数的不重复选择就是从n个数中随机选取m(m<n)个数.在本文中,我们用Java来实现.因此我们先介绍Java的相关知识. 在Java中,Java.util.Set接口和Java.util.L ...

  8. android的Devices窗口中Online显示成Offline

    这种情况几率很低,如果出现,点击Reset adb就好了.

  9. linux下用gtk+写比赛赌博GUI小游戏

    游戏界面全部由gtk的GUI完成,没有使用openGL之类的高端货. 游戏玩法就是8位选手比赛跑步,你可以在赛前赌哪位选手会赢,如果输了cash会被扣除,反之cash会增加. 无聊写了3个选项:小数时 ...

  10. Media Player Classic - HC 源代码分析 2:核心类 (CMainFrame)(1)

    ===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...