赞
踩
Hive是基于Hadoop的一个数据仓库系统,在各大公司都有广泛的应用。大多数人在使用hive的过程中都会使用hive sql来查询数据,那么hive是怎么将sql语句变成我我们想要的数据呢?
阅读下面文章前,需要您先了解MapReduce的基本运行过程,如果您已经了解MapReduce的基本运行过程,那请您继续阅读。若您对MapReduce的基本运行过程不是很熟悉,请跳转到该链接【mapreduce过程】,阅读后再回来阅读下文内容。
详细讲解SQL编译为MapReduce之前,我们先来看看MapReduce框架实现SQL基本操作的原理。
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端完成连接操作。下面将详细介绍这两种的区别。
MapJoin简单说就是在Map阶段将小表读入内存,顺序扫描大表完成Join。
上图是Hive MapJoin的原理图,出自Facebook工程师Liyin Tang的一篇介绍Join优化的slice,从图中可以看出MapJoin分为两个阶段:
CommonJoinResolver优化器就是将CommonJoin转化为MapJoin,转化过程如下
深度优先遍历Task Tree
找到JoinOperator,判断左右表数据量大小
对与小表 + 大表 => MapJoinTask,对于小/大表 + 中间表 => ConditionalTask
遍历上一个阶段生成的MapReduce任务,发现JOIN[8]中有一张表为临时表,先对Stage-2进行深度拷贝(由于需要保留原始执行计划为Backup
Plan,所以这里将执行计划拷贝了一份),生成一个MapJoinOperator替代JoinOperator,然后生成一个MapReduceLocalWork读取小表生成HashTableFiles上传至DistributedCache中。
MapReduceTask经过变换后的执行计划如下图所示
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。
SELECT
name
,rank
,count(1) AS cnt
FROM TEST
GROUP BY name, rank;
- Map阶段接收的数据量和计算量基本是恒定的,不会产生数据倾斜;
- 而Shuffle阶段我们基本不能控制,也不存在数据倾斜;
- Reduce阶段会根据该key对应的数据量的不同,进行不同的计算量,上例中,第二个reduce需要一次合并计算,而13不需要计算,每个reduce的计算量不同,这便是数据倾斜,而最终的计算时间,取决于最慢的那个reduce。
了解了MapReduce实现SQL基本操作之后,我们来看看Hive是如何将SQL转化为MapReduce任务的,整个编译过程分为六个阶段:
参考文章:https://www.aboutyun.com//forum.php/?mod=viewthread&tid=20461&extra=page%3D1&page=1&
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。