hive十亿级以上数据全局排序的一种实现方式

大数据时代,日常工作中经常会处理数以亿计的数据。
笔者近期就遇到了一个十亿级以上的数据排序需求,并输出序号。
如果是小规模数据我们直接使用row_number全局排序就可以了,但是当数据规模达到十亿或者以上时,直接使用row_number肯定是不太现实。
因为全局排序的时候变成了单节点任务,要么超内存,要么就超时。

经过几轮调试,问题解决了,并且性能还不错,笔者把处理这个问题的思路与解决方案分享出来与网友交流学习。

目标全局排序15亿条记录,排序字段是一个概率分(分值在0-1之间)。
由于直接使用row_number肯定不能解决。大数据处理还是需要分布式的思想,笔者首先想到的是根据数据大小对数据进行分段排序,然后在合并逐段的排序结果形成全局排序结果(归并排序的一种特殊形式)。
因为有15亿数据,分成1000段,平均每个reduce处理150W。
想好了,直接写代码开干。

with t1 as
(
    select id,p,ceil(p*1000) as sub_level,
    row_number() over(partition by ceil(p*1000) order by p) as sub_order
    from table_source
),
t2 as (

    select sub_level,(sum(cnt) over(order by sub_level) - cnt) as base_order
    from
    (

        select sub_level,count(1) as cnt
        from t1
        group by sub_level
    ) t
)

select id,p,base_order + sub_order as global_order
from t1
left join t2 on t1.sub_level = t2.sub_level
;

由于数据分布不均匀,上面的代码运行直接部分节点爆内存了。
那么就粗暴的加大分桶数量直接到5000(把上面代码中的1000修改成5000),再运行就成功了。
但是耗时4800s。相对较长,分析发现主要是分桶不均匀导致长尾效益。

这种粗暴的分桶方式对于数据分布比较均匀的场景比较适合,但是对于数据分布不均匀的场景可能就比较低效。
那么我们该怎么优化一下呢?

由于问题是数据分桶不均匀导致的,那么我从分桶均的角度来解决。

  • 首先查看排序数据的分布
select ceil(p*1000) as sub_level, count(1)
from table_source
group by ceil(p*1000)
order by 2 desc;

根据结果发现数据在四个区间分布比较
(0,0.05] 分布占大部分
(0.05,0.056]分布比较密集
(0.057,0.061]分布高度密集
(0.061,0.15)分布较少
我们根据这个4个区间的数据量分布进行定值化分段,让分桶尽量均匀。

定制化分段后的sql如下,

with t0 as (
    select id, p,
    case
        when p  0.05 then ceil(600 * (p-0.0) / (0.05-0.0))
        when p  0.056 then 600 + ceil(400 * (p-0.05) / (0.056-0.05))
        when p  0.061 then 800 + ceil(200 * (p-0.056) / (0.061-0.056))
        else 1201
    end as sub_level
    from table_source
),
t1 as
(
    select id,p,sub_level,
    row_number() over(partition by sub_level order by p) as sub_order
    from t0
),
t2 as (
    select sub_level,(sum(cnt) over(order by sub_level) - cnt) as base_order
    from
    (
        select sub_level,count(1) as cnt
        from t1
        group by sub_level
    ) t
)

select id,p,base_order + sub_order as global_order
from t1
left join t2 on t1.sub_level = t2.sub_level

这个sql相对之前粗暴分段的方式数据分布均匀多了,性能也大大提升。耗时不到原来的一半。

  • 1.大数据处理任何时候都要有分布式处理的思想,避免把分布式问题变成单机任务的场景。
  • 2.分布式任务要尽量保证数据分布均匀,不均匀分布的数据任务就会出现长尾,导致任务耗时长,且容易单节点内存超限。

Original: https://blog.csdn.net/eaglejava2015/article/details/126594170
Author: 爱吃苦瓜的猿
Title: hive十亿级以上数据全局排序的一种实现方式

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/817712/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球