文章为个人整理,欢迎指正补充
1、set hive.optimize.skewjoin=true,开启优化
set hive.skewjoin.key=100000 ,key超过这个条数就进行优化
两个参数一般同时使用,join产生倾斜时开启,目的在于将产生倾斜的key通过map side join处理,其它key正常在reduce端join
2、map side join
set hive.auto.convert.join=true;
set hive.mapjoin.smalltbale.filesize; 默认为25mb,其中一个表小于该值时自动优化
3、group by 优化
set hive.groupby.skewindata=true;
将一个mapreduce转换成两个mapreduce,第一个mapreduce将key随机写到不同的reduce中,第二个mr是做真正的聚合操作
4、count(distinct)
discinct需要在reduce端做,count又限制了只能有一个reduce,所以效率很低
select count(*) from (select distinct col from tableA)t;
5、开启并行化执行
set hive.exec.parallel=true;
资源换取时间的方式
6、本地化执行
hive大多数job需要提交到集群执行,在数据量很小的情况下是没有必要的,将job提交到集群的时间甚至比查询的时间还多,对于这种情况,hive可以在单台节点上处理job
满足本地化执行条件:
a、job输入数据小于 hive.exec.mode.local.auto.inputbytes.max(默认128mb)
b、job的map数小于hive.exec.mode.local.auto.tasks.max(默认为4)
c、job的reduce数为0或者1
7、调整任务map数
对于每个不满足切片大小的文件都会产生一个map task,如果输入的小文件过多,会产生大量map task,大量map task的启动和初始化会浪费很多的时间和资源。但是对于文件大小不大;
但是文件内记录很多,则需要增加map数和reduce数(mapred.reduce.tasks),提高任务并行度
set mapred.max.split.size,
切片大小计算:
minSize=max{minSplitSize,mapred.min.split.size}
maxSize=mapred.max.split.size
splitSize=max{minSize,min{maxSize,blockSize}}
8、JVM重用
当小文件过多,或者task数量很多且执行时间短会导致jvm频繁启停,浪费较多资源和时间,set mapred.job.reuse.jvm.num.tasks=20;(默认为1)
JVM重用可以启动一次jvm进程,运行一个job中的多个task后销毁
9、启用严格模式set hive.mapred.mode=strict;
严格模式下:
对分区表查询必须限制分区
使用order by同时须使用limit,避免对数据全排序
避免产生笛卡尔积,导致执行时间过长
10、关闭推测执行
因为导致某个task执行时间过长的原因往往是数据倾斜,此时开启推测执行就是在浪费资源