hive优化数据倾斜的解决方法

转自:http://blog.csdn.net/lpxuan151009/article/details/7980509

生数据,通常的象是:

  • 务进长时间维持在99%(或100%),看任务监面,发现只有少量(1个或几个)reduce子任未完成。
  • 看未完成的子任,可以看到本地写数据量累非常大,通常超10GB可以为发生数据斜。

数据斜一般是由于代中的joingroup bydistinctkey分布不均致的,大量经验表明数据斜的原因是人的建表疏忽或业务可以避的。如果确认业务需要这样倾斜的逻辑.

 

  • join,使用map join,即在查询头添加map join hint,例如

select /*+MAPJOIN(b)*/ * from a join b on a.id =b.id

将会把join转换为mapjoin,且将b表作小表理。

  • group bydistinct,使用两次MR化,即定参数: hive.groupby.skewindata=true
  • 随机数解决数据倾斜



一、随机函数解决倾斜

 

原始sql:

insertoverwrite table t_aa_click_log partition (pt=’${yyyymmddhh}’)

selecta.*

from(select * from t_aa_click_log1

wherept=’${yyyymmddhh}’

)a

leftouter join

(select* from t_aa_pv_info_log

wherept=’${yyyymmddhh}’) b

ona.pvid=b.pvid;

 

发现大量时间花费在reduce99%~100%这最后一步上,约占总时长20分钟的一半,

用以下sql检查下数据分布:

select*

from(

selectpvid,count(1) cnt

fromt_aa_click_log1

wherept=’${yyyymmddhh}’

groupby pvid) t

orderby cnt desc

limit50;

 

发现pvid=’NA’的占比最高,有100多万,而其他最多的也只有几十条,证实数据倾斜。

 

利用随机函数,将pvid=’NA’的数据随机分布到不同的reduce中:

insertoverwrite table t_aa_click_log partition (pt=’${yyyymmddhh}’)

selecta.*

from(select * from t_aa_click_log1

wherept=’${yyyymmddhh}’

)a

leftouter join

(select* from t_aa_pv_info_log

wherept=’${yyyymmddhh}’) b

–如果pvid长度<=2,包含pvid=NA或-1 等多种异常值,即用随机函数叠加处理,因为异常值本来就关联不到,所以加上随机函数对结果没有影响

oncase when length(a.pvid)<=2 then concat(a.pvid,rand()) else a.pvid end =b.pvid;

 

问题解决。


二、MAPJOIN 结合 UNIONALL

 

原始sql:

select a.*,coalesce(c.categoryid,’NA’) as app_category

from (select * from t_aa_pvid_ctr_hour_js_mes1

) a

left outer join

(select * fromt_qd_cmfu_book_info_mes

) c

on a.app_id=c.book_id;

 

速度很慢,老办法,先查下数据分布。

select *

from

(selectapp_id,count(1) cnt

fromt_aa_pvid_ctr_hour_js_mes1

group by app_id) t

order by cnt DESC

limit 50;

 

数据分布如下:

NA      617370129

2       118293314

1       40673814

d       20151236

b       1846306

s       1124246

5       675240

8       642231

6       611104

t       596973

4       579473

3       489516

7       475999

9       373395

107580  10508

 

我们可以看到除了NA是有问题的异常值,还有appid=1~9的数据也很多,而这些数据是可以关联到的,所以这里不能简单的随机函数了。而t_qd_cmfu_book_info_mes这张app库表,又有几百万数据,太大以致不能放入内存使用mapjoin。

 

解决方案:

select a.*,coalesce(c.categoryid,’NA’) as app_category

from –if app_id isnot number value or <=9,then not join

(select * fromt_aa_pvid_ctr_hour_js_mes1

where cast(app_id asint)>9

) a

left outer join

(select * fromt_qd_cmfu_book_info_mes

where cast(book_id asint)>9) c

on a.app_id=c.book_id

union all

select /*+ MAPJOIN(c)*/

a.*,coalesce(c.categoryid,’NA’) as app_category

from –if app_id<=9,use map join

(select * fromt_aa_pvid_ctr_hour_js_mes1

wherecoalesce(cast(app_id as int),-999)<=9) a

left outer join

(select * fromt_qd_cmfu_book_info_mes

where cast(book_id asint)<=9) c

–if app_id is notnumber value,then not join

on a.app_id=c.book_id

 

首先将appid=NA和1~9的数据存入一组,并使用mapjoin与维表(维表也限定appid=1~9,这样内存就放得下了)关联,而除此之外的数据存入另一组,使用普通的join,最后使用union

all 放到一起。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值