【Hive-优化】Hive的优化方式四(数据倾斜优化)

  • 1)关联优化器
  • 2)数据倾斜Skewin
  • 2.1.基础查询数据倾斜
  • 2.2.表连接数据倾斜(Join skew in)
  • 2.3.分组统计数据倾斜(Groupby skew in)


1)关联优化器

在Hive的一些复杂关联查询中,可能同时还包含有group by等能够触发shuffle的操作,有些时候shuffle操作是可以共享的,通过关联优化器选项,可以尽量减少复杂查询中的shuffle,从而提升性能。

set hive.optimize.correlation=true;

2)数据倾斜Skewin

2.1.基础查询数据倾斜

如果数据量很大或者出现了数据倾斜比较严重的情况,如何来优化呢?

(1)map join

(2)Bucket-Map join

(3)SMB join

2.2.表连接数据倾斜(Join skew in)

(1)运行时优化(默认关闭)

set hive.optimize.skewjoin=true;

如果大表和大表进行join操作,则可采用skewjoin(倾斜关联)来开启对倾斜数据的优化

  • skewjoin原理:
    1、对于skewjoin.key,在执行job时,将它们存入临时的HDFS目录,其它数据正常执行
    2、对倾斜数据开启map join操作(多个map并行处理),对非倾斜值采取普通join操作
    3、将倾斜数据集和非倾斜数据集进行合并Union操作。
  • 开启skewin以后,究竟多大的数据才会被认为是倾斜了的数据呢?
#默认值100000。
set hive.skewjoin.key=100000;

如果join的key对应的记录条数超过这个值,就认为这个key产生了数据倾斜,则会对其进行分拆优化。

(2)编译时优化

上面的配置项其实应该理解为hive.optimize.skewjoin.runtime,也就是sql运行时来对偏斜信息进行优化;除此之外还有另外一个配置(默认关闭):

set hive.optimize.skewjoin.compiletime=true;

此参数的用处和上面的hive.optimize.skewjoin一致,但在编译sql时就已经将执行计划优化完毕。

但要注意的是,只有在表的元数据中存储的有数据倾斜信息时,才能生效。因此建议runtime和compiletime都设置为true。

可以通过建表语句来指定数据倾斜元数据:

CREATE TABLE list_bucket_single (key STRING, value STRING)
-- 倾斜的字段和需要拆分的key值
SKEWED BY (key) ON (1,5,6)
--  为倾斜值创建子目录单独存放
[STORED AS DIRECTORIES];

(3)Union优化

应用了表连接倾斜优化以后,会在执行计划中插入一个新的union操作,此时建议开启对union的优化配置(默认关闭):

set hive.optimize.union.remove=true;

此项配置减少对Union all子查询中间结果的二次读写,可以避免union输出的额外扫描过程,当我们开启了skewjoin时尤其有用,建议同时开启。

set hive.optimize.skewjoin=true;

set hive.optimize.skewjoin.compiletime=true;

set hive.optimize.union.remove=true;

2.3.分组统计数据倾斜(Groupby skew in)

(1)Map阶段聚合(默认开启)

hive.map.aggr=true;

开启map端combiner。此配置可以在group by语句中提高HiveQL聚合的执行性能。
这个设置可以将顶层的聚合操作放在Map阶段执行,从而减轻数据传输和Reduce阶段的执行时间,提升总体性能。

(2)两个MRJob(默认关闭)

hive.groupby.skewindata=true;

这个配置项是用于决定group by操作是否支持倾斜数据的负载均衡处理。当数据出现倾斜时,如果该变量设置为true,那么Hive会自动进行负载均衡。

当选项设定为true,生成的查询计划会有两个 MR Job。

  • 第一个MR Job,Map 的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的。
  • 第二个MR Job,再根据预处理的数据结果按照Group By Key分布到`Reduce中(这个过程可以保证相同的Group By Key被分布到同一个Reduce中),最后完成最终的聚合操作。

注意

在多个列上进行的去重操作与hive环境变量hive.groupby.skewindata存在冲突。

hive.groupby.skewindata=true时,hive不支持多列上的去重操作,并报错:

Error in semantic analysis: DISTINCT on different columns notsupported
with skew in data.

比如:1、2、3能够正常执行,但是4会报错。

(1) SELECT count(DISTINCT uid) FROM log;
(2) SELECT ip, count(DISTINCT uid) FROM log GROUP BY ip;
(3) SELECT ip, count(DISTINCT uid, uname) FROMlog GROUP BY ip;
(4) SELECT ip, count(DISTINCT uid), count(DISTINCT uname) FROMlog GROUP BY ip;