默认情况下,
Map
阶段同一
Key
数据分发给一个
reduce
,当一个
key
数据过大时就倾斜
了。
![](https://i-blog.csdnimg.cn/blog_migrate/12937a42212007d8f6de3ad8c04b4555.png)
并不是所有的聚合操作都需要在
Reduce
端完成,很多聚合操作都可以先在
Map
端进行
部分聚合,最后在
Reduce
端得出最终结果。
1
)开启
Map
端聚合参数设置
(1)是否在
Map
端进行聚合,默认为
True
set hive.map.aggr = true
(2)在
Map
端进行聚合操作的条目数目
set hive.groupby.mapaggr.checkinterval = 100000
(3)有数据倾斜的时候进行负载均衡(默认是
false
)
set hive.groupby.skewindata = true
当选项设定为
true
,生成的查询计划会有两个
MR Job
。
第一个
MR Job
中,
Map
的输出
结果会随机分布到
Reduce
中,每个
Reduce
做部分聚合操作,并输出结果,这样处理的结果
是相同的
Group By Key
有可能被分发到不同的
Reduce
中,从而达到负载均衡的目的;第二
个
MR Job
再根据预处理的数据结果按照
Group By Key
分布到
Reduce
中(这个过程可以保证
相同的
Group By Key
被分布到同一个
Reduce
中),最后完成最终的聚合操作。
![](https://i-blog.csdnimg.cn/blog_migrate/a35ff8758a6ef2575f7c912f5c636970.png)
4.4 Count(Distinct) 去重统计
数据量小的时候无所谓,数据量大的情况下,由于
COUNT DISTINCT
操作需要用一个
Reduce Task
来完成,这一个
Reduce
需要处理的数据量太大,就会导致整个
Job
很难完成,
一般
COUNT DISTINCT
使用先
GROUP BY
再
COUNT
的方式替换
,
但是需要注意
group by
造成
的数据倾斜问题
.
1
)
案例实操
(1)创建一张大表
![](https://i-blog.csdnimg.cn/blog_migrate/0badc236237197b13876e9e6c8d71a20.png)
(2)加载数据
![](https://i-blog.csdnimg.cn/blog_migrate/e699e1ecfa1fa7c24cb900b4e1b84f69.png)
(3)设置
5
个
reduce
个数
set mapreduce.job.reduces = 5;
(4)执行去重
id
查询
![](https://i-blog.csdnimg.cn/blog_migrate/c16edbd888dd831d447a2c2289f4e9e7.png)
(5)采用
GROUP by
去重
id
![](https://i-blog.csdnimg.cn/blog_migrate/4c5f425951b597745e31d61c9eb61b37.png)
虽然会多用一个 Job 来完成,但在数据量大的情况下,这个绝对是值得的
4.5 笛卡尔积
尽量避免笛卡尔积,
join
的时候不加
on
条件,或者无效的
on
条件,
Hive
只能使用
1
个
reducer
来完成笛卡尔积
4.6 行列过滤
列处理:在
SELECT
中,只拿需要的列,如果有分区,尽量使用分区过滤,少用
SELECT
*
。
行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在
Where
后面,
那么就会先全表关联,之后再过滤,比如:
案例实操:
1
)测试先关联两张表,再用
where
条件过滤
![](https://i-blog.csdnimg.cn/blog_migrate/e446cafd339ccfda97110cc6016a6132.png)
2)通过子查询后,再关联表