Hive On Spark 调优
本篇博客将从hive on spark的SQL层面,来对任务做一些优化。下面的优化,从这几个方面来讲:Group、Join、并行度、小文件。
Group、Join
$\color{ForestGreen}{小提示:}$
Group和Join的不同之处在于:
- Group 需要Reduce
- Join 可以没有Reduce
其实无论是 Group还是Join,它们均有一些通用的解决方案:
-
我们在map阶段下手。提前进行聚合。这样就会减少Shuffle。
这里面两者较为不同的是实现方式。
因为$\color{ForestGreen}{Group}$是一张表。所以就只是在map阶段进行预聚合。
但$\color{ForestGreen}{Join}$是两张表。所以它想做到预聚合,这就需要缓存一张表。
-
在reduce阶段做文章。再开一个MR任务。也就是二次聚合。
只不过,这两者的实现方式,也是较为不同。
$\color{ForestGreen}{Group}$是在map阶段添加随机数。然后在第一个Reduce中,聚合一部分。然后去掉随机数。再进行最后的聚合。
$\color{ForestGreen}{Join}$是在map和第一个Reduce里面不做任何修改。只是将Reduce中那些Key特别多的。单独再开一个任务,执行Map Join。
这样对于Group的优化就讲完了。
对于Join 还有一些优化:
SMB Join:要求分桶有序,并且两张表的桶数是倍数关系。
并行度
一般Map阶段的并行度我们通常不需要管他。我们主要关注的是Reduce阶段的并行度。
Reduce并行度相关的参数:
--指定Reduce端并行度,默认值为-1,表示用户未指定
set mapreduce.job.reduces;
--Reduce端并行度最大值
set hive.exec.reducers.max;
--单个Reduce Task计算的数据量,用于估算Reduce并行度
set hive.exec.reducers.bytes.per.reducer;
但是我们一般都不会手动指定。都是自动指定。
但是现在的自动指定也有一些问题:只能统计表级别的信息,所以对于进入Reduce端的数据量,它统计的并不准确。
需要开启以下参数:
--执行DML语句时,收集表级别的统计信息
set hive.stats.autogather=true;
--执行DML语句时,收集字段级别的统计信息
set hive.stats.column.autogather=true;
--计算Reduce并行度时,从上游Operator统计信息获得输入数据量
set hive.spark.use.op.stats=true;
--计算Reduce并行度时,使用列级别的统计信息估算输入数据量
set hive.stats.fetch.column.stats=true;
小文件
小文件又可以分为Map端和Reduce端的小文件处理方式:
-
Map端:对小文件进行合并。
--可将多个小文件切片,合并为一个切片,进而由一个map任务处理 set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
-
Reduce端:将输出的小文件,合并成大文件。
--开启合并Hive on Spark任务输出的小文件 set hive.merge.sparkfiles=true;