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

HiveSQL解析原理:包括SQL转化为MapReduce过程及MapReduce如何实现基本SQL *** 作,第1张

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

HiveSQL解析原理:包括SQL转化为MapReduce过程及MapReduce如何实现基本SQL *** 作
  • 一、MapReduce实现基本SQL *** 作的原理
    • 1、join的实现原理
      • Map Join的实现原理
        • CommonJoinResolver优化器
      • Reduce Join的实现原理
    • 3、Group By的实现原理
  • 二、SQL转化为MapReduce的过程

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&

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5698628.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存