Hive里面的数据倾斜以及解决方法

Hive数据倾斜解析
本文深入探讨了Hive中数据倾斜的问题,分析了其产生的原因,包括groupby操作、小文件过多、map和reduce数量不当、count(distinct)操作及join操作等场景,并提供了详细的解决方案,如设置hive.map.aggr和hive.groupby.skewindata参数、合并小文件、调整map和reduce任务数、使用替代SQL语法和mapjoin策略。

数据倾斜是进行大数据计算时最经常遇到的问题之一。当我们在执行HiveQL或者运行MapReduce作业时候,如果遇到一直卡在map100%,reduce99%一般就是遇到了数据倾斜的问题。数据倾斜其实是进行分布式计算的时候,某些节点的计算能力比较强或者需要计算的数据比较少,早早执行完了,某些节点计算的能力较差或者由于此节点需要计算的数据比较多,导致出现其他节点的reduce阶段任务执行完成,但是这种节点的数据处理任务还没有执行完成。

  在hive中产生数据倾斜的原因和解决方法:

  1)group by,我使用Hive对数据做一些类型统计的时候遇到过某种类型的数据量特别多,而其他类型数据的数据量特别少。当按照类型进行group by的时候,会将相同的group by字段的reduce任务需要的数据拉取到同一个节点进行聚合,而当其中每一组的数据量过大时,会出现其他组的计算已经完成而这里还没计算完成,其他节点的一直等待这个节点的任务执行完成,所以会看到一直map 100%  reduce 99%的情况。

  解决方法:set hive.map.aggr=true

       set hive.groupby.skewindata=true

  原理:hive.map.aggr=true 这个配置项代表是否在map端进行聚合

     hive.groupby.skwindata=true 当选项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。

  2)map和reduce优化。

    1.当出现小文件过多,需要合并小文件。可以通过set hive.merge.mapfiles=true来解决。

       2.单个文件大小稍稍大于配置的block块的大写,此时需要适当增加map的个数。解决方法:set mapred.map.tasks个数

       3.文件大小适中,但map端计算量非常大,如select id,count(*),sum(case when...),sum(case when...)...需要增加map个数。解决方法:set mapred.map.tasks个数,set mapred.reduce.tasks个数

  3)当HiveQL中包含count(distinct)时

         如果数据量非常大,执行如select a,count(distinct b) from t group by a;类型的SQL时,会出现数据倾斜的问题。

         解决方法:使用sum...group by代替。如select a,sum(1) from (select a, b from t group by a,b) group by a;

  4)当遇到一个大表和一个小表进行join操作时。

    解决方法:使用mapjoin 将小表加载到内存中。

    如:select /*+ MAPJOIN(a) */ 

          a.c1, b.c1 ,b.c2

     from a join b 

     where a.c1 = b.c1; 

  5)遇到需要进行join的但是关联字段有数据为空,如表一的id需要和表二的id进行关联

     解决方法1:id为空的不参与关联

    比如:select * from log a 

      join users b 

      on a.id is not null and a.id = b.id 

       union all 

       select * from log a 

      where a.id is null; 

   解决方法2:给空值分配随机的key值

      如:select * from log a 

        left outer join users b 

        on 

        case when a.user_id is null 

        then concat(‘hive’,rand() ) 

        else a.user_id end = b.user_id; 

参考博客:https://www.cnblogs.com/kongcong/p/7777092.html

### 数据倾斜的原因分析 数据倾斜通常发生在某些键值对应的数据量远大于其他键值的情况,这会导致部分节点的任务执行时间显著增加,从而拖慢整个作业的完成进度。在Hive中,这种现象可能由多种因素引起,例如连接操作、分组聚合以及分布式排序等[^1]。 --- ### 解决Hive数据倾斜方法和最佳实践 #### 方法一:调整MapReduce参数 通过设置合理的并行度和内存分配策略,可以有效缓解因资源不足引发的数据倾斜问题。具体可以通过以下方式实现: - 增加`mapreduce.job.reduces`的数量以减少单个Reducer的压力。 - 调整`hive.exec.reducers.bytes.per.reducer`参数控制每个Reducer处理的数据大小,默认值为256MB,可根据实际需求修改[^1]。 #### 方法二:使用Skew Join优化 当Join操作涉及大量偏斜的Key时,启用Skewed Join功能可以帮助平衡负载分布。此特性允许将频繁出现的大Key单独存储到不同的文件夹下分别计算后再合并结果集。开启方法如下所示: ```sql SET hive.optimize.skewjoin=true; ``` 此外还可以指定具体的倾斜阈值比例来触发该机制的应用场景设定。 #### 方法三:引入随机前缀法 对于GROUP BY类SQL语句容易产生的热点分区情况,则可考虑采用添加伪列的方式打散原有记录分布模式进而达到均匀化目的;比如下面例子展示的就是如何利用MD5哈希函数生成额外字段辅助分流效果: ```sql SELECT SUBSTR(MD5(transaction_id), 1, 8) AS rand_prefix, COUNT(*) FROM transactions GROUP BY rand_prefix, transaction_id; ``` 这种方法虽然增加了中间层运算成本但能很好地规避极端条件下少数几个桶承担过多工作负荷的风险[^2]。 #### 方法四:预处理输入源消除潜在隐患 提前对原始表做ETL转换剔除异常值或者拆分子任务独立运行也是常见手段之一 。例如针对日期格式不一致的问题我们可以统一标准化表达形式避免后续环节因为解析失败而造成不必要的麻烦 : ```sql WITH cleaned_data AS ( SELECT *, CASE WHEN tran_time LIKE '%AM%' OR tran_time LIKE '%PM%' THEN UNIX_TIMESTAMP(tran_time, 'h:mm a') ELSE UNIX_TIMESTAMP(CONCAT('0', tran_time), 'HH:mm') END AS normalized_time FROM raw_transactions ) INSERT INTO processed_table ... ``` 以上代码片段示范了怎样把不同样式的time字符串映射成标准秒级数值表示以便于进一步统计分析[^3]。 --- ### 结论 综上所述,在应对Hive框架下的大数据环境里不可避免会遇到诸如性能瓶颈之类的挑战 ,然而借助恰当的技术方案总能找到合适的解决方案克服困难达成目标效率最大化的同时保障质量稳定性不受影响 。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值