这是一种 Hive 非常常见的问题, 下面让我们学习下 如何优化
需求, 统计 明细表 里面有多少不同的明细 id
数据规模 : 全量抽取的 MySQL 数据表,按天分区,每天存储所有的MySQL 记录。
所选分区在 2亿 左右的数据量, 大小在 40 GB 规模。
我们使用最常见的 SQL 进行统计
select count(distinct detail_id)
from xd_t_als_cardoffer_detail
where p_day_id = '2019-05-15';
++++++++++++++++
| c0 |
+++++++++++++++
| 226920273 |
+++++++++++++++
1 row selected (400.344 seconds)
INFO : The url to track the job : ....
....
INFO : Hadoop job information for Stage-1: number of mapper 333; number of reducers: 1
可以看到我们的reducer 只使用了1个,相当于将所有数据都传到了一台机器运行,非常拖慢性能。
优化思路 :
将数据分散,充分利用 集群的优势。
使用
SELECT COUNT(1)
FROM (
SELECT xx_id
FROM org_table
GROUP BY xx_id
) tmp_table ;
的通用方案,
对于上述需求,我们可以这么操作 :
select count(1) from (
select detail_id
from xd_t_als_cardoffer_detail where p_day_id = '2019-05-15' group by detail_id
) tmp;
++++++++++++++++
| c0 |
+++++++++++++++
| 226920273 |
+++++++++++++++
1 row selected (64.088 seconds)
INFO : The url to track the job : ....
...
INFO : Hadoop job information for stage-1; number of mappers: 333; number of reducers: 84
--------------------------------------------------
INFO : Hadoop job information for stage-1; number of mappers: 333; number of reducers: 84
可以看到我们使用了 84 个 reducer , 充分利用了集群的优势
时间 也从最初的 400s 下降到了 64s
注意 :
我们这里尝试设置 reducer 数量看能否进一步优化 :
0: jdbc:hive2://offlinenode1:1000/default> set mapreduce.job.reducers=200;
select count(1) from (
select detail_id
from xd_t_als_cardoffer_detail where p_day_id = '2019-05-15' group by detail_id
) tmp;
++++++++++++++++
| c0 |
+++++++++++++++
| 226920273 |
+++++++++++++++
1 row selected (394.578 seconds)
INFO : The url to track the job : ....
...
INFO : Hadoop job information for stage-1; number of mappers: 333; number of reducers: 200
我这里尝试将 reducer 设置为 200 个,但是可以看到 运算时间 并没有减少,反而增加了。
我理解 由于 以下两点 导致运算的时间增加了 :
1.由于申请了更多 的 reducer ,增加了申请资源的时间开销,许多 reducer 并没有数据流入,所以并没有减少时间开销。
2. reducer 在聚合数据的时候有许多空的 reducer, 无形增加了 聚合的时间开销