hive 常见调优方法:
- 0.11前版本开启MapJoin,之后的版本默认开启
MapJoin是Hive的一种优化操作,其适用于小表JOIN大表的场景,由于表的JOIN操作是在Map端且在内存进行的,所以其并不需要启动Reduce任务也就不需要经过shuffle阶段,从而能在一定程度上节省资源提高JOIN效率 - 行列过滤
列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT *。
行处理:在分区剪裁中,当使用外关联时,只拿需要的分区,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤。
//过滤前
SELECT a.id FROM bigtable a LEFT JOIN ori b ON a.id = b.id WHERE b.id <= 10;
//过滤后
SELECT a.id FROM ori a LEFT JOIN bigtable b ON (b.id <= 10 AND a.id = b.id);
- 采用分桶技术
- 采用分区技术
- 合理设置map数
减少map数:合并小文件
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
set mapred.max.split.size=100000000;
set mapred.min.split.size.per.node=100000000;
set mapred.min.split.size.per.rack=100000000;
前面三个参数确定合并文件块的大小,大于文件块大小128m的,按照128m来分隔,小于128m,大于100m的,按照100m来分隔,把那些小于100m的(包括小文件和分隔大文件剩下的)进行合并
增加map数
set mapred.reduce.tasks=10;
create table t_1 as
select * from t
distribute by rand(123);
此时会将a表的记录,随机的分散到包含10个文件的t_1表中,再用t_1代替上面sql中的t表,则会用10个map任务去完成。
每个map任务处理大于12M(几百万记录)的数据,效率肯定会好很多。
- 合理设置Reduce数
reduce个数的设定极大影响任务执行效率,默认如果reduce的输入(map的输出)总大小不超过1G,那么只会有一个reduce任务;用了order by 则永远只有一个reduce
- 增加
调整reduce个数方法一:
调整hive.exec.reducers.bytes.per.reducer参数的值;
set hive.exec.reducers.bytes.per.reducer=500000000; (500M)
select pt,count(1) from table where pt = '2019-01-01' group by pt; 这次有20个reduce
调整reduce个数方法二;
set mapred.reduce.tasks = 10;
select pt,count(1) from table where pt = '2019-01-01' group by pt;这次有10个reduce
- 减少
set mapred.reduce.tasks= ;
启动和初始化reduce也会消耗时间和资源,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
,是否有笛卡尔积。
7.常用参数
SET hive.merge.mapfiles = true; -- 默认true,在map-only任务结束时合并小文件
SET hive.merge.mapredfiles = true; -- 默认false,在map-reduce任务结束时合并小文件(比如只有map的任务)
SET hive.merge.size.per.task = 268435456; -- 默认256M
SET hive.merge.smallfiles.avgsize = 16777216; -- 当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge