因为Hive的默认执行引擎为MR,所以基于Hive的参数调优,主要还是MR的参数调优以及Hive客户端的一些设置
1.开启Hive map阶段及reduce压缩参数:
在MR中使用压缩需要从输入,中间,输出三个阶段去选择不同的压缩方式,输入阶段可能更看重的是数据是否支持split,支持split可以增加Map输入个数而增加计算并行度,如选择可分割的Bzip2和Lzo(Lzo压缩格式要建立索引),中间map输出要考虑下阶段reduce输入带来的压缩与解压CPU时间开销,如选择压缩解压速率较快的Snappy,最终输出如果不作为其他依赖任务的输入,更加考虑的是磁盘存储上的开销,如选择高压缩比的Bzip2
开启map阶段使用压缩参数:
set hive.exec.compress.intermediate=true
set mapred.map.output.compression=true
set mapred.map.output.compression.codec= org.apache.hadoop.io.compress.SnappyCodec
开启reduce最终输出使用压缩参数:
set hive.exec.compress.output=true
set mapred.output.compression=true
set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec
set mapred.output.compression.type=BLOCK
2.设置Map与Reduce个数增加并行:
Map输入个数是根据split size大小来划分,默认是一个block块一个map,若单个文件小于一个block大小,那个也会作为一个map输入,MapReduce计算split size 大小是由computeSplitSize函数算出:
protected long computeSplitSize(long blockSize, long minSize,
long maxSize) {
return Math.max(minSize, Math.min(maxSize, blockSize));
}
可以看出,当最大值设置大于一个块大小时,split size为一个block大小,若想增加map输入并行度,则需设置最大值小于一个block,反之,若想减少map输入并行度,则需设置最小值大于一个block大小
参数设置:
set mapred.max.split.size=xxx
set mapred.min.split.size=xxx
set mapred.min.split.size.per.node=xxx
set mapred.min.split.size.per.rack=xxx
也可直接设置map数和reduce数
set mapreduce.job.maps(mapred.map.tasks)=n
set mapreduce.job.reduces(mapred.reduce.tasks)=n
若不设置reduce个数,Hive将自己去计算Reduce个数(默认为-1),
由以下参数控制:
set hive.exec.reducers.bytes.per.reducer=xxx
set hive.exec.reducers.max=n
参数设置:
Hive.fetch.task.conversion 默认为minimal
修改配置文件hive-site.xml
hive.fetch.task.conversion
more
Some select queries can be converted to single FETCH task
minimizing latency.Currently the query should be single
sourced not having any subquery and should not have
any aggregations or distincts (which incurrs RS),
lateral views and joins.
1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only
2. more : SELECT, FILTER, LIMIT only (+TABLESAMPLE, virtual columns)
或者当前session修改
hive> set hive.fetch.task.conversion=more;
执行SELECT id, money FROM m limit 10; 不走mr
参数设置:
set hive.exec.parallel=true
set hive.exec.parallel.thread.number=8
参数设置:
set mapred.job.reuse.jvm.num.tasks=n
参数设置:
set mapreduce.map.speculative=true
set mapred.map.tasks.speculative.execution=true
set mapreduce.reduce.speculative=true
set mapred.reduce.tasks.speculative.execution=true
参数设置:
set hive.auto.convert.join=true
hive.auto.convert.join.noconditionaltask.size=xxx
参数设置:
set hive.auto.convert.sortmerge.join=true;
set hive.optimize.bucketmapjoin = true;
set hive.optimize.bucketmapjoin.sortedmerge = true;
set hive.auto.convert.sortmerge.join.noconditionaltask=true;
参数设置:
set hive.optimize.ppd=true
参数设置:
set hive.map.aggr=true
参数设置:
//输入
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
//map 输出
set hive.merge.mapfiles = true
//reduce 输出
set hive.merge.mapredfiles = true
//小文件阈值
set hive.merge.smallfiles.avgsize=xxx
//最终合并文件大小
set hive.merge.size.per.task=256*1024*1024
Group by 导致的数据倾斜
当选项设定为true,生成的查询计划会有两个MR Job。当第一个MR Job中,Map的输出结果结合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果。这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的。第二个MR Job再根据预处理的数据结果按照Group By Key分布到reduce中,这个过程可以保证相同的key被分到同一个reduce中,最后完成最终的聚合操作
参数设置:
set hive.groupby.skewindata=true
参数设置:
set mapreduce.map.memory.mb=4096
set mapreduce.reduce.memory.mb=8192
where条件优化
优化前(关系数据库不用考虑会自动优化):
select m.cid,u.id from order m join customer u on( m.cid =u.id )where m.dt=‘20180808’;
优化后(where条件在map端执行而不是在reduce端执行):
select m.cid,u.id from (select * from order where dt=‘20180818’) m join customer u on( m.cid =u.id);
union优化
尽量不要使用union (union 去掉重复的记录)而是使用 union all 然后在用group by 去重
count distinct优化
尽量不要使用count (distinct cloumn) ,使用子查询
select count(1) from (select id from tablename group by id) tmp
用in 来代替join
如果需要根据一个表的字段来约束另为一个表,尽量用in来代替join
select id,name from tb1 a join tb2 b on(a.id = b.id);
select id,name from tb1 where id in(select id from tb2); in 要比join 快
善用explain查看抽象语法树(DAG)