这里写自定义目录标题
Hive背后的Mapper调优
1,Mapper数过大,会产生大量的小文件,由于Mapper是基于虚拟机的,过多的Mapper创建和初始化及关闭虚拟机都会消耗大量的硬件资源;
Mapper数太少,并发度太小,Job执行时间过长,无法充分利用分布式硬件资源
2,Mapper数由什么决定呢?
输入文件数目
输入文件大小
配置参数
默认情况下:例如一个文件800M,Block大小是128M,那么Mapper数目就是7个(6< 800/128 <7),6个Mapper处理的数据是128M,1个
Mapper处理的数据是32M;再例如,一个目录下有3个文件大小分别为5M,10M,150M,此时会产生4个Mapper,处理的数据分别是5M,
10M,128M,22M
为什么要控制Mapper的个数?
例如上面的例子中128M的Mapper运行的特别慢,但其他3个Mapper运行的很快
减少Mapper的个数,就要合并小文件,这种小文件有可能是直接来自数据源的小文件,也可能是Reducer产生的小文件;使用合并器
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
set hive.merge.mapFiles=true;#map端的合并
set hive.merge.mapredFiles=true;#reducer端的合并
set hive.merge.size.per.task=256000000;#每个map处理多大的数据,单位是字节
set mapred.max.split.size=256000000;#每个切分map的最大大小
set mapred.min.split.size.per.node=128000000;#每个切分map的最小大小
增加Mapper的个数,一般是通过控制Hive SQL中上一个Job的Reducer个数来控制的,例如在Join操作时会把多个表分解为多个Job
set mapred.map.tasks=2;
set hive.merge.mapFiles=true;
set hive.merge.mapredFiles=true;
set hive.merge.size.per.task=256000000;
例如我们有5个300M的文件;按照上面的配置会产生10个Mapper,5个Mapper处理的都是256M的数据,另外5个Mapper处理的都是44M的数据,
这样就会产生数据倾斜
如何解决,设置:
set mapred.map.tasks=6,此时根据MapRed的运行机制,会划分6个Mapper,每个Mapper的处理数据大小是256M,min(1500/6,256M)=250M
Hive背后的Reducer调优
1,Reducer个数过大的话,会产生很多小文件,每个Reducer都会产生一个文件,如果这些小文件是下一个Job的输入,则需要对小文件进行合并;
同样启动、初始化和销毁Reducer的虚拟机也需要消耗大量的硬件;
Reducer个数过小的话,Reducer的时间会比较长,也可能会出现数据倾斜;
2,如何控制Reducer的个数呢?
set hive.exec.reducers.byte.per.reducer=1G;#每个reducer能够处理的数据大小,合并之后可能就是100M的数据???
set hive.exec.reducers.max=999#最多可以设置reducer的个数
Reducer个数=min(999,Reducer的数据输入总量/1G)
set mapred.reduce.tasks=10;#默认是1,如果当前的Reducer的结果很大,且被接下来多个Job使用其结果,我们该如何设置参数?
一般都需要调大该参数;
什么情况下只有一个Reducer?
如果不进行group by但却需要汇总,或者说order by,当然如果最后Reducer的数据小于默认的1G的话,也会只有1个Reducer;