Hive常见优化

一、数据倾斜

1、什么是数据倾斜?Hadoop 框架的特性决定最怕数据倾斜

•由于数据分布不均匀,造成数据大量的集中到一点,造成数据热点。

节点间数据分布不均衡,会造成 map 端每个 map 任务的工作量不同,即 map 端数据倾斜。

Map-reduce,把相同 key 提交给同一个 reduce,如果 key 不均衡就会造成不同的 reduce 的

工作量不同。 以京东首页活动为例,曝光率大的是大活动,曝光率小的是小活动:

假如 reduce1 处理的是小活动,reduce2 处理大活动,reduce2 干的活比其他 reduce 多很多, 会出现其他 reduce 执行完毕了,reduce2 还在缓慢执行。

症状:map 阶段快,reduce 阶段非常慢; 某些 map 很快,某些 map 很慢; 某些 reduce 很快,某些 reduce 奇慢。

如下情况: A、数据在节点上分布不均匀

B、join 时 on 关键词中个别值量很大(如 null 值)

C、count(distinct ),在数据量大的情况下,容易数据倾斜,因为 count(distinct)是按 group by 字

段分组,按 distinct 字段排序。

其中 A 无法避免。B 见后边的 Join 章节。C 语法上有时无法避免

如何解决数据倾斜?实际上是没办法避免的,这里的解决只是个别情况起效: 有数据倾斜的时候进行负载均衡

set hive.groupby.skewindata = false;

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

二、 Join 、MapJoin、Group by

Join

按照 join 的 key 进行分发,而在 join 左边的表的部分数据会首先读入内存,如果左边表 的 key 相对分散(或少,分散的意思是相同 key 的数据量小),join 任务执行会比较快;而如 果左边的表 key 比较集中(key 的大小量级分化),而这张表的数据量很大,那么数据倾斜就 会比较严重。

Map 阶段同一 Key 数据分发给同一个 reduce。

Join 原则:

小表 Join 大表,原因是在 Join 操作的 Reduce 阶段(不是 Map 阶段),位于 Join 左

边的表的内容会被加载进内存,将条目少的表放在左边,可以有效减少发生内存溢出的几率。 多个表关联时,最好分拆成小段,避免大 sql(无法控制中间 Job)。

多表 Join on 条件相同时合并为一个 Map-Reduce,做 OUTER JOIN 的时候也是一样,查看 执行计划 explain
比如查询,3 个表关联:

select pt.page_id,count(t.url) PV from rpt_page_type pt
join

(select url_page_id,url from trackinfo where ds=’2013-10-11’) t on pt.page_id=t.url_page_id
join

(select page_id from rpt_page_kpi_new where ds=’2013-10-11’) r on t.url_page_id=r.page_id
group by pt.page_id;

比较 2 个表关联:

select pt.page_id,count(t.url) PV from rpt_page_type pt
join

(select url_page_id,url from trackinfo where ds=’2013-10-11’) t on pt.page_id=t.url_page_id
group by pt.page_id;

利用这个特性,可以把相同 join on 条件的放在一个 job 处理。

如果 Join 的条件不相同,如:

5000 万,纬度表 每日 2 亿,按日增量表

INSERT OVERWRITE TABLE page_pv select pt.page_id,count(t.url) PV from rpt_page_type pt

join

(select url_page_id,url,province_id from trackinfo where ds=’2013-10-11’) t on pt.page_id=t.url_page_id
join

(select page_id,province_id from rpt_page_kpi_new where ds=’2013-10-11’) r on t.province_id=r.province_id
group by pt.page_id;

大表 Join 大表

访户未登录时,日志中 userid 是空,在用 user_id 进行 hash 分桶的时候,会将日志中 userid 为空的数据分到一起,导致了过大空 key 造成倾斜。

解决办法:

把空值的 key 变成一个字符串加上随机数,把倾斜的数据分到不同的 reduce 上, 由于 null 值关联不上,处理后并不影响最终结果

案例:

End_user

Trackinfo

原写法:

select u.id,t.url,t.track_time from end_user u

join

(select end_user_id,url,track_time from trackinfo where ds=’2013-12-01’) t on u.id=t.end_user_id limit 2;

调整为:

select u.id,t.url,t.track_time from end_user u

join

(select case when end_user_id=’null’ or end_user_id is null

then cast (concat(‘00000000_’,floor(rand()*1000000)) as bigint) else end_user_id end end_user_id ,
url,track_time

from trackinfo where ds=’2013-12-01’) t on u.id=t.end_user_id limit 2;
此例子只是为了说明原理。

当前这个场景不需要这么麻烦,如下即可: select u.id,t.url,t.track_time

from end_user u

猜你喜欢

转载自blog.csdn.net/qq_33624952/article/details/79619917
今日推荐