要想做好hive优化,首先要理解MR过程,HiveSQL转换为MR的过程,以及Hive表的分区分桶机制。
本质上的优化是,减少读,避免shuffle 和 增加并发度。
优化的手段:
跳过不必要的读 | 减少Shuffle | 读延迟问题 | 数据倾斜 |
---|---|---|---|
Partition、Bucket 使用 Skew(hive对声明了Skew的列会单独使用文件存储,并且在资源分配上有优待) | MapJoin(Broadcast Join),避免ReduceJoin | 增加热数据备份数 | 对于倾斜部分单独拿出来,做Map Join |
ORCFile => 支持只读需要的列 | Sort-Merge-Bucket Join | 启动短路读(Short-Circuit Read),即不通过网络客户端,而是直接读取本地文件 | 将倾斜Key绑定一个随机数R,先按key、R做一次Shuffle,聚合减少数据量,然后再按Key做Shuffle聚合。 |
使用Tez |
Shuffle Sort/ Map Reduce 原理理解
Map Shuffle 过程:
(1)读取block,并切分为多个split,每个split对应一个map task。
(2)按Key 进行 Partition,内存排序,排序结果放入缓存,缓存不够发生溢写。
(3)溢写文件和内存中数据最终归并排序输出Map的结果,最后合并成了一个已分区且已排序的文件。
Reduce Shuffle 过程:
(1)Reduce Task 通过Copy方式,拉取Map task输出的文件,每次传输来的数据都是有序的。
(2)拉取的数据写缓存,缓存不够造成溢写。
(3)每个Ruduce任务,会直接将各个溢写的文件归并排序的结果作为输入,产出reudce的结果。
Hive SQL To Mapreduce 过程(感谢美团团队整理)
Join的实现原理
使用Join 关联的字段作为Key,并为Value打上不同的表来源标识。
在map的输出value中为不同表的数据打上tag标记,在reduce阶段根据tag判断数据来源。MapReduce的过程如下 (这里只是说明最基本的Join的实现,还有其他的实现方式)
Group By的实现原理
Group By 的字段组合作为Key,并且Map端预聚合
select rank, isonline, count(*) from city group by rank, isonline; 将GroupBy的字段组合为map的输出key值,利用MapReduce的排序,在reduce阶段保存LastKey区分不同的 key。MapReduce的过程如下(当然这里只是说明Reduce端的非Hash聚合过程)
Distinct的实现原理
单个distinct,使用group字段和distinct字段作为排序Key,Group字段作为分区Key,在Reduce阶段保存LastKey(因为排序后每组是按key有序的,因此只需使用一个LastKey作为去重字段)
select dealid, count(distinct uid) num from order group by dealid;
当只有一个distinct字段时,如果不考虑Map阶段的Hash GroupBy,只需要将GroupBy字段和Distinct字段组合为 map输出key,利用mapreduce的排序,同时将GroupBy字段作为reduce的key,在reduce阶段保存LastKey即可完成去 重
如果有多个distinct字段呢,如下面的SQL sele