Hive性能优化
hive配置角度优化:
(1)列剪裁
hive在查询时,只查询用到的列
(2)分区裁剪
hive在查询时将分区放入子查询中查询更加高效,可以减少读入的分区数目
(3)join优化
在编写带有join的语句时,将条目少的放在join操作符的左边,因为在reduce阶段,位于join操作符左边的数据会被加载到内存,载入条目较少的表,可以减少oom,所以对于同一个key来说,对应的value值小的放前,大的放后,这便是小表放前原则。
(4)map join操作
join操作在map阶段进行,不在需要reduce
大表join大表:(1)null id匹配不上,先过滤空id。
(2)业务需要不能过滤null id,给key为空的字段添加一个随机数:eg insert overwrite table A
select n.* from B full join C on
case when A.id is null then concat('hive',rand()) else V.id end =B.id(
注意:
这里拼接要跟原先数据保证join 不上)
关联时如果有条件,先子查询再关联
eg:select o.id from bigtable b join ori o on b.id=o.id where o.id<=10
改成:
select b.id from bigtable b join (select id from ori where id <=10) o on b.id=o.id
(5)group by 操作:默认情况下,Map阶段同一个Key数据分发给一个reduce,当一个Key数据过大时就倾斜了。
事实上并不是所有的聚合操作都需要在reduce端进行,很多聚合操作都可以现在map端进行部分聚合,然后reduce端得出最终结果。
map端部分聚合
这里需要修改的参数为:
hive.map.aggr=true(用于设定是否在 map 端进行聚合,默认值为真) hive.groupby.mapaggr.checkinterval=100000(用于设定 map 端进行聚合操作的条目数)
- 有数据倾斜时进行负载均衡
此处需要设定 hive.groupby.skewindata,当选项设定为 true 是,生成的查询计划有两 个 MapReduce 任务。在第一个 MapReduce 中,map 的输出结果集合会随机分布到 reduce 中, 每个 reduce 做部分聚合操作,并输出结果。这样处理的结果是,相同的 Group By Key 有可 能分发到不同的 reduce 中,从而达到负载均衡的目的;第二个 MapReduce 任务再根据预处 理的数据结果按照 Group By Key 分布到 reduce 中(这个过程可以保证相同的 Group By Key 分布到同一个 reduce 中),最后完成最终的聚合操作。
Count(distinct)去重统计【容易OOM】
数据量小的时候无所谓,数据量大的情况下,由于count distinct 操作需要用一个reduce task来完成,这一个reduce需要处理的数据量太大,就会导致整个Job很难完成,一般
count distinct 使用先group by 再count 的方式替换。
(6)合并小文件
我们知道文件数目小,容易在文件存储端造成瓶颈,给 HDFS 带来压力,影响处理效率。对此,可以通过合并Map和Reduce的结果文件来消除这样的影响。
用于设置合并属性的参数有:
- 是否合并Map输出文件:hive.merge.mapfiles=true(默认值为真)
- 是否合并Reduce 端输出文件:hive.merge.mapredfiles=false(默认值为假)
- 合并文件的大小:hive.merge.size.per.task=256*1000*1000(默认值为 256000000)
(7)无效id在关联时的数据倾斜问题
(8)数据类型不同关联时产生的数据倾斜问题
把数据类型转换成字符串类型