性能优化技巧:遍历复用提速多次分组

我们知道,大数据运算性能的瓶颈常常是在外存(也就是硬盘)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) ) Ajoin( select floor(id/20000000) Bid,min(amount) Bmin from topn group by floor(id/20000000) )  Bon A.Aid=B.Bid;这里的计算量大体与2相同,但有两个分组,我们将观察数据库是否会进行两次遍历。最后的JOIN运算只涉及100行数据,时间可以忽略不计。三、      SPL测试我们把Oracle做的测试用SPL再做一遍。1.        单分组单倍计算量编写SPL脚本执行测试:

A1=now()2=123=file("/home/topn/topn.ctx").create().cursor@m(id,amount;;A2)4=A3.groups@u(id%100:Aid;max(amount):Amax)5=interval@s(A1,now())2.        单分组双倍计算量编写SPL脚本执行测试:

A1=now()2=123=file("/home/topn/topn.ctx").create().cursor@m(id,amount;;A2)4=A3.groups@u(id%100+id\20000000:Aid;max(amount):Amax,min(amount):Amin)5=interval@s(A1,now())3.        双分组双倍计算量编写SPL脚本执行测试:

AB1=now()2=123=file("/home/topn/topn.ctx").create().cursor@m(id,amount;;A2)4cursor A3=A4.groups@u(id%100:Aid;max(amount):Amax)5cursor=A5.groups@u(id\20000000:Bid;max(amount):Bmax)6=A4.join@i(Aid,A5:Bid,Bid,Bmax)7=interval@s(A1,now())这里采用了SPL特有的遍历复用语法,在A3定义了游标,A4/B4和A5/B5中定义了两套针对这个游标的计算,表示会在一次游标遍历过程同时计算这两个结果。四、      分析与结论三种情况的测试用时如下表:测试结果(时间单位:秒)单分组单倍计算量单分组双倍计算量双分组双倍计算量Oracle458692878SPL336350376从Oracle的测试结果上看,双分组双倍计算量比单分组双倍计算量慢了近200秒,这不是一个可以忽略的时间了,因为两者的计算量几乎相同,这多出来的时间估计就是多做一次遍历的时间了。这说明数据库不会自动做遍历复用的优化,在双分组时会将数据表遍历两次,结果多做一次分组几乎会多出一倍的时间。而SPL采用了遍历复用的机制,三个测试的计算时间相差很小,多做一次分组并不会多一次遍历,只是多了一些复用控制的逻辑,不会变慢多少。说明一下,准备数据时把Oracle的amount字段类型设置成decimal了,所以计算速度比较慢;而SPL组表中用的是double类型,所以要快得多。但这个测试不是对比Oracle和SPL的计算性能,这些不同并不影响上面的结论。

(0)

相关推荐

  • PHP的SPL扩展库(二)对象数组与数组迭代器

    PHP的SPL扩展库(二)对象数组与数组迭代器 在 PHP 中,数组可以说是非常强大的一个数据结构类型.甚至我们可以把 PHP 中的数组说成是 PHP 的灵魂,而且这么说一点都不夸张.相比 Java ...

  • 性能优化技巧:有序定位关联提速主子关联后的过滤

    一.  问题背景与适用场景在<性能优化技巧:有序归并>中我们验证了有序归并算法提高关联性能的效果,那么还有没有进一步提升的空间呢?能不能再减少数据的读取量从而再提速呢?通常主子关联后还会再 ...

  • 揭秘 Vue.js 九个性能优化技巧

    这篇文章主要参考了 Vue.js 核心成员 Guillaume Chau 在 19 年美国的 Vue conf 分享的主题:9 Performance secrets revealed,分享中提到了九 ...

  • 性能优化技巧:前半有序时的排序

    一.  问题背景与适用场景在对数据集进行排序运算时,有时会遇到这样一种场景:数据集T已经按字段a有序,而字段b无序,现在我们要将T按a.b排序,我们称之为前半有序(a有序)的排序.此时我们能想到一种优 ...

  • 性能优化技巧:后半有序分组

    一.  问题背景与适用场景什么是后半有序?如果数据集T已经按字段a.b有序,现在我们要将T按b排序或分组时,因为在a值相同的段内,b都是有序的,这种要排序或分组的字段在分段内有序的情况就称为后半有序. ...

  • 性能优化技巧:有序分组

    一.  问题背景与适用场景通常分组计算都采用hash方案,即先计算分组字段的hash值,hash值相同的记录被分拣到一个小集合里,然后在这个小集合中遍历找分组字段值相同的聚合成一组.分组的复杂度(比较 ...

  • 性能优化技巧:大事实表与大维表关联

    一.  问题背景与适用场景在<性能优化技巧:小事实表与大维表关联>中,我们尝试了小事实表与大维表关联时的性能优化方法,该方法利用了小事实表可以装入内存的特点,将关联键汇集排序后到大维表中查 ...

  • 性能优化技巧:小事实表与大维表关联

    一.  问题背景与适用场景在主子表关联查询中,有时会遇到这样一种情况:按条件过滤后的事实表数据量很小,能够全部装载进内存或仅比内存略大一点:而要关联的维表数据量很大,比内存要大很多.这种时候,如果维表 ...

  • 性能优化技巧:附表

    一.  问题背景与适用场景在<性能优化技巧:有序归并>中我们见证了有序归并算法提升主子表的关联性能,在集算器中,还有进一步提高性能的办法-附表.集算器组表支持主子表保存在同一文件中,先用主 ...

  • 性能优化技巧:外键序号化

    一.  问题背景与适用场景在<性能优化技巧:部分预关联>一文中,我们介绍了将维表内存化并预关联的技术,但事实表与维表关联时,仍需进行hash计算和比对,怎么提高这一步的性能呢?我们今天再介 ...