背景
大数据时代,日常工作中经常会处理数以亿计的数据。笔者近期就遇到了一个十亿级以上的数据排序需求,并输出序号。如果是小规模数据我们直接使用row_number全局排序就可以了,但是当数据规模达到十亿或者以上时,直接使用row_number肯定是不太现实。因为全局排序的时候变成了单节点任务,要么超内存,要么就超时。
经过几轮调试,问题解决了,并且性能还不错,笔者把处理这个问题的思路与解决方案分享出来与网友交流学习。
解决过程
目标全局排序15亿条记录,排序字段是一个概率分(分值在0-1之间)。由于直接使用row_number肯定不能解决。大数据处理还是需要分布式的思想,笔者首先想到的是根据数据大小对数据进行分段排序,然后在合并逐段的排序结果形成全局排序结果(归并排序的一种特殊形式)。因为有15亿数据,分成1000段,平均每个reduce处理150W。想好了,直接写代码开干。
由于数据分布不均匀,上面的代码运行直接部分节点爆内存了。那么就粗暴的加大分桶数量直接到5000(把上面代码中的1000修改成5000),再运行就成功了。但是耗时4800s。相对较长,分析发现主要是分桶不均匀导致长尾效益。
这种粗暴的分桶方式对于数据分布比较均匀的场景比较适合,但是对于数据分布不均匀的场景可能就比较低效。那么我们该怎么优化一下呢?
优化过程
由于问题是数据分桶不均匀导致的,那么我从分桶均的角度来解决。
根据结果发现数据在四个区间分布比较(0,0.05] 分布占大部分(0.05,0.056]分布比较密集(0.057,0.061]分布高度密集(0.061,0.15)分布较少我们根据这个4个区间的数据量分布进行定值化分段,让分桶尽量均匀。
定制化分段后的sql如下,
这个sql相对之前粗暴分段的方式数据分布均匀多了,性能也大大提升。耗时不到原来的一半。
结语
–END–








暂无评论内容