Hive参数调优

一、Map阶段的优化(Mapphase

1.        Map数的计算公式为:
num_Map_tasks=

max[${Mapred.min.spilt.size},min(${dfs.block.size},${Mapred.max.split.size})]

Mapred.min.spilt.size指的是数据的最小分割单元大小(默认为1B

Mapred.max.split.size指的是数据的最大分割单元大小(默认为256MB

dfs.block.size指的是HDFS设置的数据块大小(这个值是在配置文件中定好的,而且Hive是获取不到的)

所以Map的数量是由Mapred.min.spilt.sizeMapred.max.split.size这两个参数的最大值决定的。如果不做修改的话一个Map Task处理256MB的数据,增大Mapred.max.split.size的值可以减少Map的数量,减少Mapred.max.split.size的值可以增大Map的数量。但是直接修改Mapred.Map.tasks是没有效果的。如果运行速度较慢,可以考虑增加Map的数量,增加并行度,如果运行速度较快,增加Map数量不太可能加快速度,反而有可能因为初始化Map使速度变慢,此时可以考虑减少Map,这样可以节省更多资源给其他Job

 

Reduce阶段的优化(Reudcephase

1.        Map数的计算公式为:
num_Reduce_tasks=

min[${Hive.exec.Reduces.max},(${input.size}/ ${Hive.exec.Reducers.bytes.per.Reducer})]

Hive.exec.Reducers.bytes.per.Reducer(默认值为1G

所以Reduce的数量是由输入的数据量大小决定的,但是Reduce的数量不能超过999,可以通过设置Hive.exec.Reducers.bytes.per.Reducer来设置Reduce的个数,也可以通过设置Mapred.Reduce.tasks来设置Reduce的数量。

MapReduce之间的优化(SpillCopySort phase

1.        在Spill阶段,由于内存不够,数据需要溢写到磁盘再排序,然后对所有的文件进行Merge。可以通过设置io.Sort.mb来增大环形缓冲区的大小,避免Spill

2.        在Copy阶段是把文件从mapCopyReduce端。默认情况下是5%Map完成时Reduce就开始启动Copy,这个时候是很浪费资源的,因为Reduce一旦启动就被占用,直到所有的Map完成,Reduce才可以进行接下来的动作。这个比例可以通过Mapred.Reduce.slowstart.completed.Maps这个参数来设置。如果觉得这么做会导致ReduceCopy的速度减慢,可以通过tasktracker.http.threads决定作为Server端的Map用于提供数据传输服务的线程数量。Mapred.Reduce.parallel.copies可以决定作为client端的Reduce同时从Map端拉取数据的并行度(一次同时从多少个Map
中拉取数据),注意参数协调一致。

一、文件格式的优化(TextFileSequenceFileRCFile

1.        Hive的默认配置可以将对个小文件合并成一个Map处理,输出时如果文件很小也会自动合并,所以不用设置了。关于文件格式,上述三种RCFile的压缩比例和查询时间都比较好一些,可以在创建表时设置指定。
例如:create tablerc_file_testid intstored asrcfile
然后设置参数set Hive.exec.compress.output=true;指定输出格式
另外可以设置Hive.default.fileformat来设定输出格式,适用于createtable as select
例如:set Hive.default.fileformat=SequenceFile; setHive.exec.compress.output=true;

SequenceFilerecordblock两种压缩方式,block压缩比更高

SetMapred.output.compression.type=BLOCK; create table seq_file_test as select *from a;

 

 

二、Job执行模式的优化

1.        HadoopJob分为三种模式,分别为本地模式、伪分布式、完全分布式。

set Hive.exec.mode.local.auto=true,此时默认情况下如果处理的文件不超过4个,并且总大小不超过128MB就会启用local模式

 

 

三、JVM重用

1.        正常情况下MapReduce启动JVM完成一个task后就退出了,如果任务花费时间短,但又要多次启动JVM的情况下(比如对很大数据量进行计数操作),JVM的启动的启动时间就会变成一个比较大的overhead(开销),这种情况下可以通过设置
Mapred.Job.reuse.jvm.num.tasks=5; 可以让JVM运行多次任务之后再退出


四、**数据倾斜**

1.        比如有个场景:未注册用户user_id=0,注册用户有唯一的user_id,那么对于user_idgroup byjoin时,某个Reduce会收到比其他Reduce更多的数据。
如果是group by造成的,有两个参数可以解决:第一个是Hive.Map.aggr,他的默认值为true,意思是会做Map端的Combiner,所以count*)是看不出区别的,但是
countdistinct)会有一些倾斜。另一个参数是Hive.groupby.skewindata,这个参数的意思是在Reduce操作时,拿到的Key不是相同值分给同一个Reduce,而是随机分发(在每个可以后面拼接随机字符串),然后Reduce做聚合,做完之后再进行一轮MR,因为要额外启动一次Job,效果不明显,不推荐使用。
如果是join造成的,可以使用skew join,其原理是把特殊值先不在Reduce端计算掉,而是先写入HDFS,然后启动一轮Map join专门做这个特殊值的计算。需要设置
set Hive.optimize.skewjoin=true; 然后根据Hive.skewjoin.key的值来判断超过多少条算特殊值。这种情况可以在SQL语句里将特殊值隔离开来避免数据倾斜:
改写前:select a.* from logs a join users b on a.user_id = b.user_id; 
改写后:
select a.* from  (  

select a.*  

from (select * from logs where user_id = 0)  a   

join (select * from users where user_id = 0) b   

on auser_id =  buser_id  

union all  

select a.*   

from logs a join users b  

on a.user_id <> 0 and auser_id = b.user_id )t; 


五、Join算法

1.        处理分布式join,一般有两种方法:
replication join
:把其中一个表复制到所有节点,这样另一个表在每个节点上面的分片就可以跟这个完整的表join了;
repartition join:把两份数据按照join key进行hash重分布,让每个节点处理hash值相同的join key数据,也就是做局部的join
MR中,replication join对应Map side joinrepartitionjoin对应Reduce side join
Hive默认使用的是Reduce side join,但是在其中一张表较小时,可以考虑使用Mapside join,因为小表的复制代价小于大表shuffle的代价。Set Hive.auto.convert.join=true;
Hive
会根据Hive.smalltable.filesize的参数来判断是否该使用Map sidejoin,默认小于25MB算小表。


猜你喜欢

转载自blog.csdn.net/dongdouzin/article/details/80769442