hive的数据倾斜解决策略

本文介绍了如何使用Hive SQL解决数据倾斜问题,包括处理NULL值、利用mapjoin优化小表关联、分散大表数据等场景,并提供了具体示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      不管是实际工作还是面试中,数据倾斜的问题永远都是不可避免会遇到的。看了一些文章,发现有的给出的hive数据倾斜解决方法里有函数关键词错误的,下面对hive中的数据倾斜用HQL解决的例子做了总结:


例如:
日志-表A :user_id(用户id) event(行为)state(状态) time(时间戳)

用户-表B :user_id(用户id)sex(性别)         age(年龄)


一、两个表相互关联,其中一个表批量出现NULL:
现在做  A left join B
(1)假如表A出现了大批量的user_id为NULL,会碰到数据倾斜的问题,而我们又要排除表A中为NULL的数据,那么可以:

select A1.* , B.*
from
(select * from A where user_id is not NULL ) A1
left join B
on A1.user_id = B.user_id

这里在left jorn 前就过滤点NULL

(2)假如表A出现了大批量的user_id为NULL,会碰到数据倾斜的问题,而我们又要查出A中为NULL的数据,那么可以:
   给为NULL的user_id替换一个随机数,考虑到user_id可能是数字,为了防止替换的随机数被匹配到,可以增加一个特殊字符'v_':

select A.* , B.*   
from A 
left join B   
on (case when A.user_id is NULL then concat('v_',rand()) else A.user_id end) = B.user_id; 

这里把user_id为NULL变成了随机数,就不存在NULL都在一起的情况了。也就解决了数据倾斜

二、两个表互相关联,其中一个是小表(一般小于二三十M),这种情况可以用 map jorn 解决数据倾斜问题,把小表放在内存中


(1)假如 B 表为小表
select /*+ MAPJOIN(B)*/  A.*,B.* 
from  
A  
left join B
on Auser_id =B.user_id 


(2)假如B 表很大,不能放入内存。并且A表日志表也很大,但是A表里面全是作弊用户刷量,也就是说A表里面虽然有很多条记录,但是实际 都是几个或是几十个,几百个相同的user_id的记录。那么我们就可以创造出一个小表,然后运用 map jorn:

select /*+mapjoin(C)*/ A.*,C.*
from A  
left join 
  (
    select  /*+mapjoin(A1)*/ B.*
      from ( select distinct user_id from A ) A1
      join B 
      on A1.user_id = B.user_id
   ) C
  on A.user_id = C.user_id;


  **这里的C表是个小表--因为之前说了,A表里面都是重复user_id的记录,经过去重 也就几个或是几十个,几百个,关联B 表的信息后 生产C表。然后最后一层  把 C表当小表 运用map jorn


三、两张大表关联,key分布不均


  假如:日志A表中的user_id 有个别几个是 作弊刷量用户(这几个user_id的日志记录条数很多),其他的user_id 正常,这样和用户B表关联可能就会出现数据倾斜。解决方案:
  可以打散表A。


select


COALESCE(D.user_id,E.user_id),
COALESCE(D.event,E.event),
COALESCE(D.state,E.state),
COALESCE(D.time,E.time),
D.sex,
D.age


from 
(
select B.user_id as B_user_id ,B.sex as sex ,B.age as age , A.user_id as user_id ,A.event as event , A.state as state ,A.time as time  from 
B
left join 
(select * from A TABLESAMPLE(BUCKET 1 out of 2 on time) ) C
on B.user_id = C.user_id 
) D


left join 


(select * from A TABLESAMPLE(BUCKET 2 out of 2 on time) ) E
on D.B_user_id = E.user_id 


这是以B表为主表。如果想要得到A表信息。最后可以在加where 条件。


**这里是把A表,按照time字段Hash取模,分成了2 个桶。目的是为了把那些相同的user_id 记录打散,分在两个表里面。(特殊情况下,不好根据字段打散时,也可以新加一列随机数字段,根据随机数打散)
经过两次left jorn 。 



COALESCE函数类似 数据库的NVL函数。
示例 
下面的语句返回值 258。 
SELECT COALESCE( NULL, 258, 1311, 0 ) 
备注 
如果所有参数均为 NULL,则 COALESCE 返回 NULL

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值