大数据之HiveSQL调优

1、HiveSQL调优概述

1.1、优化原因
①数据倾斜
②数据冗余
③Job或I/O过多
④MapReduce分配不合理
1.2、优化方式
①对HiveSQL语句本身的优化
②Hive配置项的调整
③MR的调整

2、HiveSQL本身优化

2.1、列裁剪和分区裁剪
列裁剪就是在查询时只读取需要的列,分区裁剪就是只读取需要的分区
select uid,event_type,record_data	
from calendar_record_log	
where pt_date >= 20190201 and pt_date <= 20190224	
and status = 0;
2.2、谓词下推
将SQL语句中的where谓词逻辑都尽可能提前执行,减少下游处理的数据量。
select a.uid,a.event_type,b.topic_id,b.title	
from calendar_record_log a	
left outer join (	
select uid,topic_id,title from forum_topic	
where pt_date = 20190224 and length(content) >= 100	
) b on a.uid = b.uid	
where a.pt_date = 20190224 and status = 0;
2.3、sort by代替order by
order by将结果按某字段全局排序,这会导致所有map端数据都进入一个reducer中
ort by,那么还是会视情况启动多个reducer进行排序,并且保证每个reducer内局部有序,
	为了控制map端数据分配到reducer的key,往往还要配合distribute by一同使用。
	如果不加distribute by的话,map端数据就会随机分配到reducer。
	
select uid,upload_time,event_type,record_data	
from calendar_record_log	
where pt_date >= 20190201 and pt_date <= 20190224	
distribute by uid	
sort by upload_time desc,event_type desc;

``

2.5、Join优化
hive中的Join可分为Common Join(Reduce阶段完成join)和Map Join(Map阶段完成join)
2.5.1、小表前置

Hive在解析带join的SQL语句时,会默认将最后一个表作为probe table,将前面的表作为build table并试图将它们读进内存,在维度建模数据仓库中,事实表就是probe table维度表就是build table

select a.event_type,a.event_code,a.event_desc,b.upload_time	
from calendar_event_code a	
inner join (		
select event_type,upload_time from calendar_record_log	
where pt_date = 20190225	
) b on a.event_type = b.event_type;
2.5.2、多表join时key相同
这种情况会将多个join合并为一个MR job来处理
select a.event_type,a.event_code,a.event_desc,b.upload_time	
from calendar_event_code a	
inner join (	
select event_type,upload_time from calendar_record_log	
where pt_date = 20190225	
) b on a.event_type = b.event_type	
inner join (	
select event_type,upload_time from calendar_record_log_2	
where pt_date = 20190225	
) c on a.event_type = c.event_type;
2.5.3、利用map join
map join特别适合大小表join,不等值关联的情况。Hive会将build table和probe table在map端直接完成join过程,
消灭了reduce,效率很高。

①在Hive0.11前,必须使用MAPJOIN来标记显示地启动该优化操作,由于其需要将小表加载进内存所以要注意小表的大小

select /*+ mapjoin(t1)*/ t1.a,t1.b 
from table t1 
join table2 t2 
on ( t1.a=t2.a and f.ftime=20110802)

②在Hive0.11后,Hive默认启动该优化,也就是不在需要显示的使用MAPJOIN标记,其会在必要的时候触发该优化操作将普通JOIN转换成MapJoin,可以通过以下两个属性来设置该优化的触发时机

set hive.auto.convert.join=true; //设置 MapJoin 优化自动开启,默认是开启的
set hive.mapjoin.smalltable.filesize=25000000 //设置小表不超过多大时开启 mapjoin 优化,即25M

#进行查询
select t1.a,t1.b 
from table t1 
join table2 t2 
on ( t1.a=t2.a and f.ftime=20110802)

##### 2.5.4、优化SQL处理join倾斜
1)空值或无意义值
	
	事实表是日志类数据时,往往会有一些项没有记录到,我们视情况会将它置为null,
	如果缺失的项很多,在做join时这些空值就会非常集中,拖累进度。
		
	若不需要空值数据,就提前写where语句过滤掉。
	需要保留的话,将空值key用随机方式打散,例如将用户ID为null的记录随机改为负值:
```sql
select a.uid,a.event_type,b.nickname,b.age	
from (	
select	
  (case when uid is null then cast(rand()*-10240 as int) else uid end) as uid,	
  event_type from calendar_record_log	
where pt_date >= 20190201	
) a left outer join (	
select uid,nickname,age from user_info where status = 4	
) b on a.uid = b.uid;

2)单独处理key
这其实是上面处理空值方法的拓展,不过倾斜的key变成了有意义的。一般来讲倾斜的key都很少,我们可以将它们抽样出来,对应的行单独存入临时表中,然后打上一个较小的随机数前缀(比如0~9),最后再进行聚合。SQL语句与上面的相仿,不再赘述。

3)不同数据类型

	如果不转换类型,计算key的hash值时默认是以int型做的,
	这就导致所有“真正的”string型key都分配到一个reducer上。所以要注意类型转换:
select a.uid,a.event_type,b.record_data	
from calendar_record_log a	
left outer join (	
select uid,event_type from calendar_record_log_2	
where pt_date = 20190228	
) b on a.uid = b.uid and b.event_type = cast(a.event_type as string)	
where a.pt_date = 20190228;

4)build table过大

	全量用户维度表过大,无法使用map join的地步,而使用普通join又有数据不均的问题。

	处理方式:这时就要充分利用probe table的限制条件,削减build table的数据量,再使用map join解决
select /*+mapjoin(b)*/ a.uid,a.event_type,b.status,b.extra_info	
from calendar_record_log a	
left outer join (	
select /*+mapjoin(s)*/ t.uid,t.status,t.extra_info	
from (select distinct uid from calendar_record_log where pt_date = 20190228) s	
inner join user_info t on s.uid = t.uid	
) b on a.uid = b.uid	
where a.pt_date = 20190228;

3、hive优化

一个map或者reduce任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。
3.1、map阶段优化
使单个map任务处理合适的数据量。
3.1.1、map参数设置
mapred.min.split.size:数据的最小分割单元;min值默认是1KB。
mapred.max.split.size:数据的最大分割单元;max值默认是256M。
通过调整max可以起到调整map数的作用,减小max可以增加map数;增加min可以减少map数。
3.1.2、map切分
假设input目录下有1个文件a,大小是780M,
那么map默认参数会把a分成7块(6个128M和1个 12M),从而产生7个map。

假设input目录下有3个文件a,b,c,大小分别为10M,20M,130M,
那么hadoop会把文件分成4块(10M,20M,128M,2M),从而产生4个map数。
3.1.3、解决方式
通过以下方法来在map执行前合并小文件,减少map数:
set mapred.max.split.size=128000000;  			// 能分割块的最大块大小
set mapred.min.split.size.per.node=100000000;	// 每个节点处理的最小split
set mapred.min.split.size.per.rack=100000000;	// 每个机架处理的最小split
***前面三个参数确定合并文件块的大小,大于文件块大小128m的,按照128m来分隔,
小于128m,大于100m的,按照100m来分隔,把那些小于100m的(包括小文件和分隔大文件剩下的),
进行合并。

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;  // 合并文件
***这个参数表示执行前进行小文件合并。
3.2、reduce阶段优化
Reduce设置的过大,那么将会产生很多小文件,
hive.exec.reducers.bytes.per.reducer(每个reduce任务处理的数据量,默认为1000^3=1G)	
hive.exec.reducers.max(每个任务最大的reduce数,默认为999)
3.3、合并小文件
是否合并Map输出文件:hive.merge.mapfiles=true(默认值为真)
是否合并Reduce 端输出文件:hive.merge.mapredfiles=false(默认值为假)
合并文件的大小:hive.merge.size.per.task=25610001000(默认值为 256000000)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

随缘清风殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值