Hive优化----利用随机数避免数据倾斜

本文详细阐述了数据倾斜现象及其解决策略,重点介绍了如何使用随机函数来解决倾斜问题,并通过示例SQL操作展示了实现过程。通过调整SQL查询逻辑,有效地减少了查询时间,提高了数据处理效率。
生数据,通常的象是:

     任务进长时间维持在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;

 

问题解决。

<think>我们正在处理Hive数据倾斜的问题。根据引用内容,数据倾斜发生在JOIN、GROUP BY等操作中,某些节点处理的数据量远大于其他节点,导致性能瓶颈。用户要求查找处理方法,并且我们有一些引用资料可供参考。 引用[2]提到,不能仅仅罗列通用方法,而要结合具体业务场景和数据特征进行分析。因此,在回答时,我们需要强调分析的重要性,并针对不同情况给出具体策略。 引用[3]提到,Hive可以自动处理倾斜连接(skew join),它会检测倾斜的键值(超过阈值的键),并将这些倾斜数据分成小批次分配给多个Reducer处理。这需要我们设置参数(如hive.skewjoin.key)并开启相关配置。 引用[4]指出,Reduce端数据倾斜很多是由Count distinct问题引起的,因此要避免数据膨胀。对于Join阶段的N值问题,要对表的数据分布有清楚认识。 引用[5]提供了更具体的处理方法: - 情况3(join表连接时出现数据倾斜)的解决方案:mapjoin、大表打散、小表扩容、smbjoin。 - 大表打散:通过添加随机前缀将大表数据打散到多个分区,然后再聚合。 - 小表扩容:将小表复制多份广播到每个节点。 此外,引用[5]还提到分组聚合时的数据倾斜处理:分两步聚合(第一步加随机前缀聚合,第二步去掉前缀再聚合)。 因此,我们可以将处理方法分为几个类别,并结合具体场景说明。 回答结构建议: 1. 首先强调分析数据的重要性(引用[2])。 2. 分组聚合(Group By)导致的数据倾斜处理方法。 3. Join操作导致的数据倾斜处理方法(包括mapjoin、大表打散、小表扩容等)。 4. Count Distinct导致的数据倾斜处理方法(引用[4])。 5. 其他通用方法(如调整参数、增加Reducer等)以及注意事项。 注意:在回答中要自然引用,即在对应的策略后面添加引用标识。 下面开始组织回答内容。 </think>### Hive 数据倾斜处理方法详解 数据倾斜Hive 分布式计算中的典型瓶颈,会导致某些节点负载过重,拖慢整体任务。结合业务场景和数据特征,可通过以下方法针对性解决: --- #### **一、Join 操作倾斜处理** 1. **MapJoin 广播小表** - **适用场景**:维度表(小表)关联事实表(大表) - **原理**:将小表加载到内存广播至所有节点,避免 Reduce 阶段 ```sql SET hive.auto.convert.join=true; -- 自动开启 MapJoin SET hive.mapjoin.smalltable.filesize=25000000; -- 小表阈值 (默认 25MB) SELECT /*+ MAPJOIN(dim) */ * FROM fact_table f JOIN dim_table d ON f.id = d.id; ``` - **效果**:消除 Shuffle 过程,倾斜键值不再集中[^2][^5] 2. **大表打散 + 小表扩容** - **适用场景**:大表存在热点键(如 UserID、City 等) - **步骤**: 1. **大表打散**:为倾斜键添加随机后缀分散数据 ```sql -- 打散大表 (添加 0-9 随机后缀) SELECT *, CONCAT(join_key, '_', CAST(RAND()*10 AS INT)) AS new_key FROM big_table; ``` 2. **小表扩容**:复制小表数据匹配后缀 ```sql -- 小表扩容 10 倍 SELECT d.*, num FROM dim_table d LATERAL VIEW EXPLODE(ARRAY(0,1,2,3,4,5,6,7,8,9)) tmp AS num; ``` 3. **关联计算**:用新键关联后聚合 ```sql SELECT orig_key, SUM(value) FROM ( SELECT SPLIT(b.new_key, '_')[0] AS orig_key, b.value FROM big_table_expanded b JOIN dim_table_expanded d ON b.new_key = CONCAT(d.join_key, '_', d.num) ) GROUP BY orig_key; ``` - **原理**:将热点键分散到多个 Reducer 并行处理[^5] --- #### **二、Group By 聚合倾斜处理** 1. **两级聚合** - **适用场景**:高基数分组键(如用户行为日志) - **步骤**: ```sql -- 第一级聚合:添加随机数分组 SELECT group_key, CAST(RAND()*100 AS INT) AS rand_prefix, SUM(metric) AS partial_sum FROM table GROUP BY group_key, rand_prefix; -- 第二级聚合:合并结果 SELECT group_key, SUM(partial_sum) AS total_sum FROM stage1_result GROUP BY group_key; ``` - **优势**:将单点压力分散到多轮计算[^5] 2. **启用负载均衡参数** ```sql SET hive.groupby.skewindata=true; -- 自动启动两级聚合 SET hive.groupby.mapaggr.checkinterval=100000; -- 检测倾斜阈值 ``` --- #### **三、Count Distinct 优化** 1. **改写为 Group By** ```sql -- 低效写法 (易倾斜) SELECT COUNT(DISTINCT user_id) FROM logs; -- 优化写法 SELECT COUNT(1) FROM ( SELECT user_id FROM logs GROUP BY user_id ) t; ``` 2. **预聚合分桶** ```sql -- 创建分桶表 CREATE TABLE logs_bucketed CLUSTERED BY(user_id) INTO 100 BUCKETS; -- 查询时直接桶内聚合 SELECT COUNT(DISTINCT user_id) FROM logs_bucketed; ``` - **原理**:利用分桶将数据均匀分布[^4] --- #### **四、高级参数调优** | **参数** | **作用** | 推荐值 | |----------------------------------|------------------------------------------|---------------| | `hive.skewjoin.key` | 定义倾斜键阈值 (行数) | 100000+ [^3] | | `hive.optimize.skewjoin` | 自动处理倾斜连接 | true | | `hive.skewjoin.mapjoin.map.tasks`| 处理倾斜键的 Map 任务数 | 10000 | | `mapreduce.job.reduces` | 手动增加 Reduce 数量 | 根据数据量调整 | --- #### **五、最佳实践建议** 1. **前置分析**: ```sql -- 检测倾斜键分布 SELECT key, COUNT(1) AS cnt FROM table GROUP BY key ORDER BY cnt DESC LIMIT 10; ``` 2. **避免全局排序**:用 `DISTRIBUTE BY + SORT BY` 替代 `ORDER BY` 3. **慎用动态分区**:设置 `hive.exec.max.dynamic.partitions=1000` 防溢出 > ⚠️ **关键原则**: > - 倾斜处理需结合数据分布特征(如热点键比例)[^2] > - MapJoin 对小表敏感,超限会回退到 Reduce Join > - 大表打散需权衡计算开销与倾斜收益 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值