Hive-分区取TOP N问题
问题背景
设想你对用户在不同品类上的行为打分聚合后得到这样一个表 user_cate_score
|
uid |
cate |
score |
|
1 |
1 |
0.3 |
|
2 |
2 |
0.5 |
|
8 |
3 |
0.9 |
现在,你想将每个品类的TOP 100W 用户取出来,这种场景在推荐、营销中很常见。
基本方法
这个很容易通过窗函数写出如下解法
select uid, cate, scorefrom( select uid, cate, score, row_number() over (partition by cate order by score desc) as r from user_cate_score)T where r <= 1000000
通过窗函数row_number()在每个cate分区上按照score排序,得到row_number,然后取TOP 100W即可。
问题: Hive在执行的时候由于每个partition会分到一个reducer上,这导致单个reducer处理的数据量非常大,严重拖慢执行时间,没法充分利用到分布式的效率。
改进方法
近似取TOP 100W
select uid, cate, scorefrom( select uid, cate, score, row_number() over (partition by cate,rnd order by score desc) as r from( select *, cast(rand() * 100 as int) as rnd from user_cate_score )Ta)Tbwhere r <= 10000
思路: 加上一个0-100的随机数进行partition,可以将一个cate分散到100个reducer上执行,然后对每个cate的每个reducer取TOP 1W,就近似实现了对每个cate取TOP 100W。好处,速度快了很多。
本文来自博客园,作者:业余砖家,转载请注明原文链接:https://www.cnblogs.com/yeyuzhuanjia/p/16571098.html

浙公网安备 33010602011771号