hive优化分为join优化和join无关的优化。而join相关的优化又分为mapjoin可以解决join优化和mapjoin无法解决的join优化。

离线数据处理的主要调整:数据倾斜

hive优化

是否由不良习惯引起。
需要确定以下几点:

  • 需要计算的指标是否可以直接使用汇总层。
  • 仔细考虑业务需求,尽量不浪费计算和存储资源
  • 尽量不使用select *from 这样的方式,用到哪些列就指定哪些列,where 条件中尽量添加过滤条件。以减少整个MR任务中需要处理、分发的数据量。
  • 输入文件不要是大量的小文件。

Join无关的优化

对于join无关的问题主要有group by相关的倾斜和count distinct 相关的优化

group by 引起的倾斜优化

group by 引起的倾斜主要是输入数据行按照group by 列分布不均匀引起的,比如,按照供应商对销售明细表来统计订单数,则部分供应商订单量显得非常多,部分则少。对于group by 引起的倾斜,优化可设置参数:
set hive.map.aggr = true #map输入随机
set hive.groupby.skewindata = true #根据预处理的数据按照group by 分布reduce中。

count distinct 优化

例如: select count(distinct user) from table;
由于需要去重,因此hive会把map阶段的输出全部分布到一个reduce task上,就容易引起性能问题。可以通过先group by 再count 的方式来优化,优化后sql如下:
select count(1) from (select user from table group by user ) temp
原理:利用group by去重,在统计group by 的行数目。

大表join小表优化

通过将小表广播(默认25M,最大不超过1g。hdfs显示的文件大小是压缩后的大小,当实际加载到内存市,容量会增大很多,很多场景下可能会膨胀10倍)
语法:/+mapjoin(b)/

hive 对于mapjoin是默认开启的,设置参数为:
set hive.auto.convert.join = ture;

join相关的优化:大表join大表优化

方案一:转化为mapjoin。— 限制后为小表
即广播小表。限制行和列。但是很多情况下无法解决问题

方案二:join时用case when语句 — 倾斜值是明确的而且数量很少
此种解决方案的应用场景为:倾斜值是明确的而且数量很少,比如null值引起的倾斜。核心是将这些引起倾斜的值随机分发到reduce,join时对这些这些特殊值concat随机数,进而达到分发目的。

方案三:倍数b表,再取模join — 倾斜值多
1、通用方案
思路:建立一个临时表,其值只有一列,将b表放大n倍。(select a,b.num from a join temp_table b on 1=1 )
核心:按照join的key分发会倾斜,人工增加一列进行分发,则之前倾斜程度会减为原来的1/n。弊端是b表会膨胀n倍。运行时间会有影响,可能会变多

2、专用方案
思路:将b表的大key放大倍数,其他key正常关联。建立一个临时表动态存放每日最新的大卖家。同时此表的大卖家要膨胀预先设定的倍数。如果是大卖家,则concat一个随机数。否则正常关联。运行效率效果比通用方案好很多。只是将大卖家的行数膨胀,其他不变。

方案四、动态一分为二**
方案2、3都用了一分为二的思想,但是不彻底。终极解决方案是动态一分为二。即对于倾斜的值和不倾斜的值分开处理,最后union all。
列如:找出倾斜的界限,买家数超过10000的卖家为倾斜key。
核心:需要临时表存放倾斜的键。对于倾斜的key的表b直接mapjoin(广播),不倾斜的key正常join

总结:

方案1、2 、3中通用方案都不能保证大表join大表的问题。因此方案3的专用方案方案4是本节推荐的方案。但是他们都需要新建一个临时表存储每天变化的大卖家。方案3不需要对代码框架进行修改,但是b表放大,b表一定是维表,否则是错误的。方案4的解决方法最通用,自由度高,但是对于代码的更改最大,更改代码框架,可作为最终方案解决。