性能优化技巧-程序游标-创新互联

很多算法都会产生落地的中间结果,从而影响性能,尤其是数据量较大的时候。这种情况下通常可用程序游标来避免数据落地,下面举例说明。

创新互联2013年开创至今,先为西林等服务建站,西林等地企业,进行企业商务咨询服务。为西林企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。

前半排序

计算目标:订单表原来已按时间排序,需要将数据按日期、产品去除重复,再统计记录条数。

由于去重后结果集较大,内存放不下,因此一般会用groupx去重,SPL脚本如下:


A
1=file("sales.btx").cursor@b()/从集文件读入订单记录
2=A1.groupx(date(ORDERDATE),PRODUCTID)/按日期、产品分组去重
3=A2.skip()/对游标计数

但函数groupx会导致数据落地,因此性能不高。

要使去重的中间结果不落地,可以先生成程序游标,distinctProduct.dfx脚本如下:


AB
1=file("sales.btx").cursor@b()
2for A1;date(ORDERDATE)=A2.id(PRODUCTID)
3
return B2

A2:循环订单表。由于数据已按时间排序,因此每次取日期相同的一批数。

B2:按产品去重。注意,全量数据虽大,但按天取数相对较少,内存可以放下,所以这里用id去重。

B3:返回本批次的去重结果。注意,程序游标并非一次性返回所有数据,而是每次循环之后,先等待调用者的请求,如果调用者继续要数据,程序游标才会进行下一次循环,期间数据不落地。

主程序可通过cursor函数调用程序游标,用法与普通游标类似:


A
1=cursor("distinctProduct.dfx")/调用程序游标
2=A1.skip()

        可以看到,程序游标可减少数据落地,从而提升计算性能。

 集合运算

数据库进行集合运算时要先排序,如果数据量太大,则排序会耗费大量时间,迟迟不能输出结果。在这种情况下,适合用程序游标生成不落地的有序中间结果集,从而实现快速输出。

比如两张结构相同表:callRecordA、callRecordB。两张表在时间字段callTime上建立了索引,每秒数据量万级,现在对2015-01-01这一天的数据做并集运算,需要快速输出前500条(比如在报表上快速呈现)。

这次将程序游标和调用代码写在同一个脚本中,如下:


ABC
1func=connect("orcl")
2
for 60*60*24=elapse(datetime("2015-01-01  00:00:00"),A2-1)
3

=A1.query("select  CALLTIME,OUTID,INID,DURATION,CHARGE from"+A1+"where callTime=?",B2)
4

=B3.sort(OUTID,INID,DURATION,CHARGE)
5

return B4
6
=A1.close()
7=cursor@c(A1,"callRecordA")
8=cursor@c(A1,"callRecordB")
9=[A7,A8].mergex@u()
10=A9.fetch@x(500)

A1:用func定义程序游标,相应的调用语法为cursor@c。

B2:循环一天中的每一秒。

C3:从数据库查询一秒的数据,因为是按索引取数,所以速度很快,而且对数据库影响很小。注意A1是表名变量,程序游标既可以从callRecordA取数,也可以从callRecordB取数。

C4:对一秒数据进行内存排序,以便形成有序结果集。由于数据在同一秒,所以只需对其他字段排序。

A7A8:以表名为参数,取出2个程序游标。

A9:对两个游标进行有序归并,@u表示取并集。类似地,可以用@i和@d分别进行并交集、差集运算。

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


当前名称:性能优化技巧-程序游标-创新互联
分享URL:http://scyanting.com/article/higes.html