我们都知道hive是通过把sql语句转换为mapreduce任务来完成。
mr任务的效率就完全取决于sql语句的好坏,如果我们理解了工作原理之后对效率的提升也有一定的帮助。
我们常用的语句一般是
- select
- group by
- join
下面就从hive转化为mr入手分析
首先我们先回忆mr的几个步骤:
1.输入分片
2.map阶段
3.combiner阶段(可选)
3.shuffle阶段
4.reduce阶段
4.输出阶段
其实这三个语句的解析也是这些不走,只不过它们之间存在一些差异
select阶段
输入分片
查询时from where就限制了分片的选择。比如select id from user
这个语句会在整个文件系统中查找,并且会输入整个user文件。这样是不恰当的,如果我们只是想查询某一阶段的数据的话。比如我们只想要,北京,20180808的数据:select id from user where time=20180808,where=北京
如果我们也按照time,where进行了分区分桶的话,就会直接读取分区文件并且作为输入。当然如果没有进行分区的话查找仍然是全局搜索。
当然输入后,hadoop会进行分片,如果文件小于128不操作(这个值会根据hadoop版本而不同,也可以进行设置mapred.min.split.size
)。
map阶段
map主要由分片数量决定。如果有3个分片就有三个task。并会过滤掉非分区的限制条件。比如where如果非分区。那么map就会从where的所有字段中找出北京。
reduce/shuffle
纯select无此操作
输出文件
合并输出即可。
总结
高效率select:对常用条件进行分区分桶操作。用多少字段取多少字段。
对于纯的select不涉及重分区,所以只有map操作
group by
如 select count(name) from user where time=20190901 group by city
同城人口数量
输入分片
与select相同
map阶段
map首先会根据分片创建相应多的任务。然后会输出键值对,列入<北京,1>
Comboner阶段
这个阶段是可选阶段,他的作用主要是为了使reduce更轻松也使传输更少。设想所有的map输出要把所有的<city,1>都达到reduce,而且reduce要挨个的1+1,这样会使reduce过度疲劳,也要传输大量文件。我们可以在reduce前对每个分片的数据进行1+1的汇聚。那么传送到输出reduce端的就是<city,n>,reduce只用把每个分区的数量加载一起就行。
当然,刚刚的例combonenr和reduce完成了相同的事,也可以做不同的事,用户可以自定义。
combiner操作只限定max,min,count等不影响全局的计算,因为combiner操作的数据毕竟不是全局的,只代表局部。
如果数据很多,很沉余可以使用。
Shuffle阶段
map要经过shuffle才能到reduce,shuffle也叫做奇迹诞生的地方。它的主要操作是
- 分区
- 排序
- 分割
- 复制
- 合并
同时它也分为了map端shuffle和reduce端shuffle
map端的shuffle包括环形内存缓冲区执行溢出写,partition,sort,combiner,生成溢出写文件,合并
Reduce端的shuffle主要包括三个阶段,copy,sort(merge),reduce

group by操作是需要shuffle的,map结果集是<city,1>(默认没有combiner),现在我们需要把相同city的结果分到一个reduce当中。在shuffle进行分区的时候默认使用的是hash分区,因为相同city取的hash相同,所以能成功完成分区
reduce阶段
对过来的的数据<city,Iter(1,1,1,1)>进行操作,这里我们需要count操作所以是1+1+1+1.
输出文件
同上
总结
优化仍是在输出文件的分区上。数据倾斜问题以后会写文章讨论。
join
输入分片
这里需要注意的是,join操作会对两个表进行操作,所以会同时启动两个mapreduce任务。
map阶段
两个mr分别进行数据的筛选
shuffle阶段
shuffle在这的主要作用就是分区。它会把两个表相同的数据分到一个reduce上面。默认的也是对其hash取膜,取膜的对象是On的列,每一个on操作都会对应一次shuffle操作。
reduce阶段
reduce阶段其实是一个关联的阶段,把数据整合到一起。接受的数据格式是 表1<city,111>, 表2<city,zhansan>那么经过整合后,得到的是<city,(111,zhansan)>。
试想,如果表1中有<city,111>,<city,222>,<city,333>,而表2中也有<city,yyy>,<city,www>那么reduce后得到的是什么呢。
答案是笛卡尔积,<city,(111,yyy)>,<city,(111,www)>....
输出文件
合并reduce任务后输出。
总结
join操作一般会涉及多个mapReduce,其重分区主要取决于on的列。如果三表查询,on的列相同,那么只有一次shuffle。如果on的列不同,会引发两次shuffle。
所以说join是很耗时的操作。
网友评论