简介
Hive可以快速实现简单的MapReduce统计,主要是通过自身组件把HiveQL转换成MapReduce任务来实现的。
Hive中SQL查询转换成MapReduce作业的过程
- 当用户向 Hive 输入一段命令或查询(即 HiveQL 语句)时,Hive 需要与 Hadoop 交互工作来完成该操作。
- 该命令或查询首先进入到驱动模块,由驱动模块中的编译器进行解析编译,并由优化器对该操作进行优化计算,然后交给执行器去执行。执行器通常的任务是启动一个或多个 MapReduce 任务,有时也不需要启动 MapReduce 任务。
例:
执行包含*的操作时(如 select * from 表),就是全表扫描,选择所有的属性和所有的元组,不存在投影和选择操作,因此,不需要执行 Map 和 Reduce 操作。
HiveQL 执行流程
HiveQL执行流程步骤解析
- 由 Hive 驱动模块中的编译器——Antlr 语言识别工具,对用户输入的 SQL 语言进行词法和语法解析,将 SQL 语句转化为抽象语法树(AST Tree)的形式;
- 对该抽象语法树进行遍历,进一步转化成 QueryBlock 查询单元。因为抽象语法树的结构仍很复杂,不方便直接翻译为 MapReduce 算法程序,所以,Hive 把抽象语法树进一步转化为 QueryBlock,其中,QueryBlock 是一条最基本的 SQL 语法组成单元,包括输入源、计算过程和输出三个部分;
- 再对 QueryBlock 进行遍历,生成 OperatorTree(操作树)。其中,OperatorTree由很多逻辑操作符组成,如 TableScanOperator、SelectOperator、FilterOperator、JoinOperator、GroupByOperator 和 ReduceSinkOperator 等。这些逻辑操作符可以在 Map 阶段和 Reduce 阶段完成某一特定操作;
- 通过 Hive 驱动模块中的逻辑优化器对OperatorTree 进行优化,变换 OperatorTree的形式,合并多余的操作符,从而减少 MapReduce 任务数量以及 Shuffle 阶段的数据量;
- 对优化后的 OperatorTree 进行遍历,根据 OperatorTree 中的逻辑操作符生成需要执行的 MapReduce 任务;
- 启动 Hive 驱动模块中的物理优化器,对生成的 MapReduce 任务进行优化,生成最终的 MapReduce 任务执行计划;
- 最后由 Hive 驱动模块中的执行器,对最终的 MapReduce 任务进行执行输出。
总结
Hive驱动模块中的执行器执行最终的MapReduce任务时,Hive本身是不会生成MapReduce算法程序的,他需要通过一个表示“Job执行计划”的XML文件来驱动执行内置的、原生的Mapper和Reducer模块。
Hive通过和JobTracker通信来初始化MapReduce任务,不需要直接部署在JobTracker所在的管理节点上执行。Hive要处理的数据文件通常存储在HDFS上,HDFS是由NameNode来管理的。
HiveSQL执行查询语句实例
1. 用MapReduce实现连接操作
假设参与连接(join)的两个表分别为用户表 User 和订单表 Order,User 表有两个属性,
即 uid 和 name,Order 表也有两个属性,即 uid 和 orderid,它们的连接键为公共属性 uid。
这里对两个表执行连接操作,得到用户的订单号与用户名的对应关系。
SQL查询语句如下:
select name, orderid from user u join order o on u.uid=o.uid;
过程说明:
在Map阶段,User 表以 uid 为键(key),以 name 和表的标记位(这里 User 的标记位记为 1)为值(value)进行 Map 操作,把表中记录转化成生成一系列键值对的形式。Order 表以 uid 为键,以 orderid 和表的标记位(这里表 Order 的标记位记为 2)为值进行 Map 操作,把表中记录转化成生成一系列键值对的形式。
例:
User 表中记录(1,Lily)转化为键值对(1,<1,Lily>),其中,括号中的第一个“1”是 uid 的值,第二个“1”是表 User 的标记位,用来标识这个键值对来自 User 表;再比如,Order 表中记录(1,101)转化为键值对(1,<2,101>),其中,“2”是表 Order 的标记位,用来标识这个键值对来自 Oder 表。Shuffle阶段,把 User 表和 Order 表生成的键值对按键值进行哈希,然后传送给对应的 Reduce 机器执行。
例:
比如键值对(1,<1,Lily>)、(1,<2,101>)和 (1,<2,102>)传送到同一台 Reduce 机器上,键值对
(2,<1,Tom>)和(2,<2,103>)传送到另一台 Reduce 机器上。当Reduce机器接收到这些键值对时,还需要按表的标记位对这些键值对进行排序,以优化连接操作。Reduce阶段,对同一台 Reduce 机器上的键值对,根据“值”(value)中的表标记位,对来自 User 和 Order这两个表的数据进行笛卡尔积连接操作,以生成最终的连接结果。
例:
键值对(1,<1,Lily>)与键值对(1,<2,101>)和 (1,<2,102>)的连接结果分别为(Lily ,101>)和 (Lily, 102),键值对(2,<1,Tom>)和键值对(2,<2,103>)的连接结果为(Tom, 103)。
2. 用MapReduce实现分组操作
假设分数表 Score 具有两个属性,即 rank(排名)和 level(级别),这里存在一个分组
(Group By)操作,其功能是把表 Score 的不同片段按照 rank 和 level 的组合值进行合并,计算不同 rank 和 level 的组合值分别有几条记录。
SQL查询语句如下:
select rank, level ,count(*) as value from score group by rank, level;
过程说明:
Map阶段,对表 Score 进行 Map 操作,生成一系列键值对,对于每个键值对,其键为“<rank,level>”,值为“拥有该<rank,value>组合值的记录的条数”。
例:
Score 表的第一片段中有两条记录(A,1),所以,记录(A,1)转化为键值对(<A,1>,2),Score 表的第二片段中只有一条记录(A,1),所以,记录(A,1)转化为键值对(<A,1>,1)。Shuffle阶段,对 Score 表生成的键值对,按照“键”的值进行哈希,然后根据哈希结果传送给对应的 Reduce 机器去执行。
例:
键值对(<A,1>,2)和 (<A,1>,1)传送到同一台Reduce机器上,键值对(<B,2>,1)传送到另一台Reduce机器上。然后,Reduce 机器对接收到的这些键值对,按“键”的值进行排序。Reduce阶段,对于 Reduce 机器上的这些键值对,把具有相同键的所有键值对的“值”进行累加,生成分组的最终结果。
例:
在同一台 Reduce 机器上的键值对(<A,1>,2)和 (<A,1>,1>)Reduce后的输出结果为(A,1,3),(<B,2>,1)的 Reduce 后的输出结果为(B,2,1)。
参考: