前半有序的大数据排序

本文涉及的产品
云原生大数据计算服务 MaxCompute,5000CU*H 100GB 3个月
云原生大数据计算服务MaxCompute,500CU*H 100GB 3个月
简介:

最近碰到这么一个案例,情况可以简化总结成这样:数据库中有表T,其中有两个重要的字段a和b,a是一个时间戳,精确到秒;b是用户号;其它字段用来表示用户b在时刻a发生的事件属性。

现在任务是:把数据按a,b排序导出。简单来讲,就是把SELECT * FROM T ORDER BY a,b的结果集写出到文件。

但是,这个T表有几十亿条记录,这个SQL发出去之后,数据库就象死了一样,一个多小时都没有任何反应。

这也难怪,几十亿记录的大排序确实非常慢,上T的数据量内存装不下,而外存排序需要分段读入数据,在内存将每段排序后再缓存到硬盘,然后将这些缓存数据一起再归并。这样,必须把所有数据都遍历过一遍且分段排序后才能开始输出。

还有什么别的办法么?

通用的大排序可以说已经被全世界研究到极致了,再想出一个更优的办法几乎没有可能性了。但是,如果我们能找到这些数据的一些可得特征,说不定就能有办法了。

了解到一些业务信息后,我们发现这批数据有这样一些特征:

1. 数据是按发生时刻(也就是a)为次序插入的,这样物理存储次序也就会接近于按a有序,而且数据库已经为字段a建好了索引;

2. 从某个起始时刻到终止时刻,几乎每一秒都会有数据插入;

3. 数据按时间分布比较平均,大概每秒数万条,没有某一秒的数据量特别多;

利用这些特征,我们可以设计这样的算法(用SPL写成),其中start,end分别是数据的起止时刻。


A

B

1

for interval@s(start,end)+1

=elapse@s(start,A1-1)

2


=db.query(“SELECT * FROM T WHERE a=?”,B1)

3


=B2.sort(b)

4


>outputfile.export@a(B3)

基本逻辑是:循环所有的秒,从数据库取出某一秒的记录按b排序后再写出到文件。因为数据库为a建有索引,而数据也接近于按a有序存储,用索引取数就非常快。每一秒内的数据量并不大,可以在内存中排序,速度很快。容易证明这个算法返回的结果集就是按a,b有序的,这样就不需要缓存数据就可以完成这个大排序了。

这个算法执行后立即就有数据开始输出,数小时内就完成了按序导出数据的任务,之所以需要数小时,主要还是从数据库中取数以及写入文件的时间(几十亿行和上T的数据量),排序本身几乎没有占用时间。

针对这批数据,我们还有一个任务:想知道字段a,b是否可以用作T的主键,也就是说字段a,b的取值在T表是否是唯一的。

本来用SQL做这个判断也很简单,只要看看

SELECT COUNT(*) FROM T

SELECT COUNT(*) FROM (SELECT a,b FROM T GROUP BY a,b)

是否相等就可以了(有些数据库不支持COUNT(DISTINCT a,b)写法,这里写成子查询形式)。

COUNT(*)容易算,但面对数十亿行的大数据做GROUP BY运算,其方法和外存排序是差不多的,成本也差不多,也是跑了一个多小时没动静。

但是,如果我们利用上述特征,就很容易计算出这个值:


A

B

1

for interval@s(start,end)+1

=elapse@s(start,A1-1)

2


=db.query@1(“SELECT COUNT(DISTINCT b) FROM T WHERE a=?”,B1)

3


=@+B2

类似地,循环每一秒,针对每一条记录一个COUNT(DISTINCT B),然后都加起来就是我们要的答案了(容易证明这个算法的正确性)。这段代码几分钟就完成了运算(和上例相比,这里不导出也就不需要取出明细数据了,也不必写文件,而且还能并行计算,不象上例中要有序写出就只能串行)。

细心的读者可能要问,这两个例子都是讲如何利用索引来快速计算,为什么本文标题要叫“前半有序”呢?

实际上我们就是利用了这批数据已经有的次序信息。这两个问题的关键点都是需要按a,b排序,而在索引的作用下,这批数据看起来已经对a有序了,也就是待排序字段中的前一部分字段已有序了。而如果前面字段相同时的记录数都没有大到内存放不下的地步,那么就可以不使用缓存实现大排序了。

如果数据已经存储在可以保持次序的文件中,则这个方法的适应面会更宽泛一些,不需要事先知道a的起止时刻并循环每一秒,代码也会更简单些。

假如数据文件T中按a的次序写入了T表的记录,则上面的两个问题的算法可以分别写出来是这样:


A

B

1

for file(T).cursor();a

=A1.sort(b)

2


>outputfile.export@a(B1



A

B

1

for file(T).cursor();a

=@+A1.id(b).len()

SPL中提供了针对游标的有序取出方法,上面两段代码中A1格的意思是针对文件T的数据游标循环,每次读到字段a的值发生变化时则进入循环体,然后再读下一批a相同的记录,...。

基于文件的运算比上述使用索引从数据库取数的效果又好了数倍。而且这几段代码对内存占用也非常少。本来大排序是个很耗用内存的动作,因为后一步归并的性能严重依赖于分段的数量,要减少分段,就要让每一段尽量大,所以内存越大的性能就越好。而利用前半有序的特征后,只要一点点内存(本例中只要能装入数万行记录)就可以高速完成运算了。

最后再温习一下我们的观点:性能优化要因地制宜,根据数据和运算的特征想办法。

我们不能解决通用的大排序问题,但在特定场合下却能设计出好算法提高性能。而数据库过于透明,看起来程序员不用操心了,但数据库并没有那么智能,经常不会利用数据特征来自动优化。而且,在SQL体系下,即使人为想出好算法,也几乎无法实现。


原文发布时间为:2018-11-13

本文作者:蒋步星

本文来自云栖社区合作伙伴“数据蒋堂”,了解相关信息可以关注“数据蒋堂”。

相关实践学习
基于MaxCompute的热门话题分析
本实验围绕社交用户发布的文章做了详尽的分析,通过分析能得到用户群体年龄分布,性别分布,地理位置分布,以及热门话题的热度。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps 
相关文章
|
4月前
|
SQL JSON 大数据
ElasticSearch的简单介绍与使用【进阶检索】 实时搜索 | 分布式搜索 | 全文搜索 | 大数据处理 | 搜索过滤 | 搜索排序
这篇文章是Elasticsearch的进阶使用指南,涵盖了Search API的两种检索方式、Query DSL的基本语法和多种查询示例,包括全文检索、短语匹配、多字段匹配、复合查询、结果过滤、聚合操作以及Mapping的概念和操作,还讨论了Elasticsearch 7.x和8.x版本中type概念的变更和数据迁移的方法。
ElasticSearch的简单介绍与使用【进阶检索】 实时搜索 | 分布式搜索 | 全文搜索 | 大数据处理 | 搜索过滤 | 搜索排序
|
5月前
|
缓存 算法 Java
Java中如何处理大数据量的排序?
Java中如何处理大数据量的排序?
|
存储 算法 搜索推荐
大数据管理的重要思想和算法总结----排序(上)
大数据管理的重要思想和算法总结----排序(上)
80 0
|
7月前
|
SQL 大数据 HIVE
每天一道大厂SQL题【Day04】大数据排序统计
每天一道大厂SQL题【Day04】大数据排序统计
57 0
|
存储 算法 搜索推荐
大数据管理的重要思想和算法总结----排序(下)
大数据管理的重要思想和算法总结----排序(下)
83 0
|
搜索推荐 算法 大数据
大数据开发基础的数据结构和算法的基本算法的排序
在大数据开发中,排序算法是一种基础算法。它用于对数据集合中的元素进行排序,以便更方便地进行搜索、查找、统计等操作。排序算法可以分为内部排序和外部排序两种类型。
93 0
|
关系型数据库 MySQL 大数据
【大数据系列之MySQL】(十四):MySQL中的排序查询语句
【大数据系列之MySQL】(十四):MySQL中的排序查询语句
166 0
|
大数据 API Java
大数据基础之java常用API二(数组元素排序,冒泡排序、Arrays类,包装类,Date类)
大数据基础之java常用API二(数组元素排序,冒泡排序、Arrays类,包装类,Date类)
191 0
大数据基础之java常用API二(数组元素排序,冒泡排序、Arrays类,包装类,Date类)
|
1月前
|
存储 分布式计算 数据挖掘
数据架构 ODPS 是什么?
数据架构 ODPS 是什么?
361 7