共计 1861 个字符,预计需要花费 5 分钟才能阅读完成。
咱们晓得,大数据运算性能的瓶颈经常是在外存(也就是硬盘)IO 上,因为外存拜访性能要比内存低一两个数量级。因而,做性能优化时,缩小硬盘的访问量有时要比缩小 CPU 计算量更为重要。同一个工作,如果能应用硬盘访问量更少的算法,即便 CPU 计算量不变甚至略多一点,也会取得更好的性能。
分组汇总须要对数据集进行遍历。同一个数据集可能会按不同维度进行分组,这样原则上就要遍历屡次,大数据时就会波及多遍硬盘拜访。然而,如果咱们能在一次遍历过程中计算出多个维度的分组后果,那就会缩小很多硬盘访问量。
惋惜,SQL 无奈写出这样的运算(在遍历中返回多个分组后果),只能遍历屡次,或者寄希望于数据库引擎是否能优化。而 SPL 则反对这种遍历复用的语法,能够一次遍历计算出多个分组后果,从而进步性能。
上面咱们做一下测试,以 Oracle 为例看数据库是否会对屡次遍历的计算进行优化,以及在 SPL 中采纳遍历复用算法对性能的影响。
一、数据筹备和环境
SPL 脚本生成数据文件,数据共两列,第一列 id 是小于 20 亿的随机整数,第二列 amount 是不大于 1 千万的随机实数。数据记录为 80 亿行,生成的原始文本文件大小为 169G。利用数据库提供的数据导入工具将此文件数据导入到 Oracle 的数据表 topn 中,同时也用此文件数据生成 SPL 组表文件 topn.ctx。
在一台 Intel 服务器上实现测试,2 个 Intel3014 CPU,主频 1.7G,共 12 核,内存 64G。数据库表数据及 SPL 组表文件均存储在同一块 SSD 硬盘上。
这里刻意把数据量造得比内存大,以保障操作系统不可能把这些数据都缓存进内存,理论运算时肯定会读取硬盘。
二、Oracle 测试
测试分成三种状况:单分组单倍计算量、单分组双倍计算量、双分组双倍计算量。
1. 单分组单倍计算量
select /+ parallel(12) / mod(id,100) Aid,max(amount) Amax from topn group by mod(id,100)
2. 单分组双倍计算量
select /+ parallel(12) / mod(id,100)+floor(id/20000000) Aid, max(amount) Amax, min(amount) Amin from topn group by mod(id,100)+floor(id/20000000);
计算式多了一倍,相当于计算量大了一倍。
3. 双分组双倍计算量
select /+ parallel(12) / * from (select mod(id,100) Aid,max(amount) Amax from topn group by mod(id,100) ) A
join
(select floor(id/20000000) Bid,min(amount) Bmin from topn group by floor(id/20000000) ) B
on A.Aid=B.Bid;
这里的计算量大体与 2 雷同,但有两个分组,咱们将察看数据库是否会进行两次遍历。最初的 JOIN 运算只波及 100 行数据,工夫能够忽略不计。
三、SPL 测试
咱们把 Oracle 做的测试用 SPL 再做一遍。
1. 单分组单倍计算量
编写 SPL 脚本执行测试:
2. 单分组双倍计算量
编写 SPL 脚本执行测试:
3. 双分组双倍计算量
编写 SPL 脚本执行测试:
这里采纳了 SPL 特有的遍历复用语法,在 A3 定义了游标,A4/B4 和 A5/B5 中定义了两套针对这个游标的计算,示意会在一次游标遍历过程同时计算这两个后果。
四、剖析与论断
三种状况的测试用时如下表:
测试后果(工夫单位:秒)
从 Oracle 的测试后果上看,双分组双倍计算量比单分组双倍计算量慢了近 200 秒,这不是一个能够疏忽的工夫了,因为两者的计算量简直雷同,这多进去的工夫预计就是多做一次遍历的工夫了。这阐明数据库不会主动做遍历复用的优化,在双分组时会将数据表遍历两次,后果多做一次分组简直会多出一倍的工夫。
而 SPL 采纳了遍历复用的机制,三个测试的计算工夫相差很小,多做一次分组并不会多一次遍历,只是多了一些复用管制的逻辑,不会变慢多少。
阐明一下,筹备数据时把 Oracle 的 amount 字段类型设置成 decimal 了,所以计算速度比较慢;而 SPL 组表中用的是 double 类型,所以要快得多。但这个测试不是比照 Oracle 和 SPL 的计算性能,这些不同并不影响下面的论断。