如下SQL:
select
a,
b,
sum(c)
from
table_name
where _date='2019-05-01'
group by
a,b
hive执行到某个stage一直卡着进度不动
最后判断原因应该就是group by的数据倾斜,数据探查发现,a,b分组后大部分count(*)都是个位数,有一部分是几百几千,怀疑是这块导致的数据倾斜。
但是,在where条件中排除了这部分count(*)很多的数据依然很慢。
最终使用以下SQL解决了:
SELECT
a,
b,
sum_c
FROM
(
select
a,
b,
SUM(c) OVER(PARTITION BY a, b) sum_c
from
table_name
where
_date = '2019-05-01'
) t
group by
a,
b,
sum_c
原始的查询中,直接按照a
和b
进行分组并求和,a
和b
的组合值分布不均匀,某些组合出现的频率远高于其他组合,使得这些组合的数据集中在少数几个reduce任务中,从而拖慢整个查询的速度。
而使用了OVER(PARTITION BY a, b)
的查询方式后:
-
内部子查询中使用的
SUM(c) OVER(PARTITION BY a, b)
窗口函数会在每个由a
和b
确定的分组内,预先计算c
的总和。这样做的好处是,将原本大量的原始数据在每个分组内进行了部分聚合,得到了每个分组对应的总和值sum_c
。 -
在外部查询中,再按照
a
、b
和sum_c
进行分组。此时,数据的分布相对更加均匀,因为之前已经在分组内进行了部分聚合,减少了每个分组的数据量差异。
这样一来,在进行最终的分组操作时,每个分组的数据量相对较为均衡,不会出现少数分组包含大量数据的情况,从而缓解了数据倾斜问题,提高了查询的执行效率。