HiveSQL解析原理:包括SQL转化为MapReduce过程及MapReduce如何实现基本SQL操作

Hive是基于Hadoop的一个数据仓库系统,在各大公司都有广泛的应用。大多数人在使用hive的过程中都会使用hive sql来查询数据,那么hive是怎么将sql语句变成我我们想要的数据呢?
阅读下面文章前,需要您先了解MapReduce的基本运行过程,如果您已经了解MapReduce的基本运行过程,那请您继续阅读。若您对MapReduce的基本运行过程不是很熟悉,请跳转到该链接【mapreduce过程】,阅读后再回来阅读下文内容。

一、MapReduce实现基本SQL操作的原理

详细讲解SQL编译为MapReduce之前,我们先来看看MapReduce框架实现SQL基本操作的原理。

1、join的实现原理

select 
	u.name,
	o.orderid 
from order o 
join user u 
on o.uid = u.uid;

hive的join分为Map Join和Reduce Join两种,他们的区别在于:Map Join的思想是将join中的小表复制到各个节点上,并加载到内存中;大表分片,与小表完成连接操作。
而Reduce Join的思想是将map端按照连接字段进行hash,reduce端完成连接操作。下面将详细介绍这两种的区别。

Map Join的实现原理


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

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

  • 通过MapReduce Local Task,将小表读入内存,生成HashTableFiles上传至Distributed Cache中,这里会对HashTableFiles进行压缩。
  • MapReduce Job在Map阶段,每个Mapper从Distributed Cache读取HashTableFiles到内存中,顺序扫描大表,在Map阶段直接进行Join,将数据传递给下一个MapReduce任务。

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

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

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

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

MapReduceTask经过变换后的执行计划如下图所示

  • 这种方法有明显的局限性:
    有一份数据比较小,在map端,能够把它加载在内存,并进行join操作。

Reduce Join的实现原理

  • Map阶段
    读取源表的数据,Map输出时候以Join on条件中的列为key,如果Join有多个关联键,则以这些关联键的组合作为key;
    Map输出的value为join之后所关心的(select或者where中需要用到的)列;同时在value中还会包含表的Tag信息,用于标明此value对应哪个表;
    按照key进行排序

  • Shuffle阶段
    根据key的值进行hash,并将key/value按照hash值推送至不同的reduce中,这样确保两个表中相同的key位于同一个reduce中

  • Reduce阶段
    根据key的值完成join操作,期间通过Tag来识别不同表中的数据。

  • 这种方法有2个问题:
    map阶段没有对数据瘦身,shuffle的网络传输和排序性能很低。
    reduce端对2个集合做乘积计算,很耗内存,容易导致OOM。

3、Group By的实现原理

SELECT 
	name
   ,rank
   ,count(1) 	AS cnt 
FROM TEST 
GROUP BY name, rank;
  • Map阶段
    map阶段的Key是group by字段的组合(这里是name和rank,如果SQL中存在distinct,则是group by字段外加distinct字段的组合)。如下图所示:
  • Shuffle阶段
    该阶段会根据key进行sort排序(一般是字典排序),然后分配给不同的reduce去执行下一步操作,结果如下:

    根据Shuffle出的不同key,可知会分配给三个Reduce,而针对第二个reduce任务,我们需要进一步的合并计算,因而整个流程如下:

    注意:从上述过程中,我们可以发现:
  • Map阶段接收的数据量和计算量基本是恒定的,不会产生数据倾斜;
  • 而Shuffle阶段我们基本不能控制,也不存在数据倾斜;
  • Reduce阶段会根据该key对应的数据量的不同,进行不同的计算量,上例中,第二个reduce需要一次合并计算,而13不需要计算,每个reduce的计算量不同,这便是数据倾斜,而最终的计算时间,取决于最慢的那个reduce。

二、SQL转化为MapReduce的过程

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

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

参考文章:https://www.aboutyun.com//forum.php/?mod=viewthread&tid=20461&extra=page%3D1&page=1&

  • 1
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嗷嗷的特Man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值