性能优化技巧——位置利用

SPL的特征之一是数据有序,适当地利用位置,可以显著提高性能。让我们先从一个典型场景开始,逐步掌握利用位置的各种技巧。

快速查询

对排序后的数据进行二分查找,可以获得较高的性能,但有些算法需用到原始顺序,看上去似乎不该再排序。比如下面的案例:

PerformanceRanking.txt有三个字段,分别是empID(销售员编号),大(部门名称)、数量(销售额)。该文件记录着各部门各销售员本季度的业绩排名,已按销售额逆序存放,现在需根据指定的销售员ID,计算出:他应当再增加多少销售额,才能提高业绩排名。如果该员工已经是第1名,则无需增加销售额。

本算法需要用排名高一位的销售员的销售额,减去该销售员的销售额,即对原始数据做相对位置计算。既然要用到原始顺序,似乎就不该再排序,否则两者难以互转,而且其他算法可能用到原始数据。这种思路下会把脚本写成这样:


有所=文件(“PerformanceRanking.txt") .import@t()/读取数据2=A1.pselect (empID: 10)/不利用位置,按empID查询记录序号3=A1.calc (A2,如果(#祝辞1,[1]量量,0))/在原始数据中做相对位置计算

上述脚本没有对数据排序,所以不能进行二分查找,性能不高。

事实上,我们可以在保留原始数据的前提下,利用位置进行排序,从而提高查询性能。脚本如下:


AB5=最新=A1.psort (empID)/排序后记录在原数据中的位置6=指数=A1(最新)/利用位置制造排序数据7=最新(指数。pselect@b (empID: 10))/二分查找,获得序8号=A1.calc (A7,如果(#祝辞1,[1]量量,0))/在原始数据中做相对位置计算

A5:函数psort只获得排序后记录在原数据中的位置,并不会对原数据真正排序。

A6:利用详细的制造一份排序后的数据。注意,此时原数据不受影响,而且详细的可以作为排序后数据指数和原始数据之间互转的桥梁。

A7:对排序后的数据做二分查找,并转回原始数据中对应的记录序号。

,

为了验证利用位置之前,之后两种算法的性能差别,可以随机取出销售员编号做参数,用循环模拟大量访问,并分别执行两种算法。如下:


AB10=100000。(A1(兰德(A1.len ()) + 1) .empID)/制造1万个empID11=现在()
12 A10=A1.pselect (empID A12): 13
=A1.calc (B12,如果(#祝辞1,[1]量量,0))14=interval@ms (A11,现在())/不利用位置,耗时:13552毫秒15

16=现在()
17 A10=最新(指数。pselect@b (empID:第A17)) 18
=A1.calc (B17,如果(#祝辞1,[1]量量,0))19=interval@ms (A16,现在())/利用位置,耗时:165毫秒

,,,,,,可以看的到,利用位置后性能提高几十倍。例子中数据量较少,随着数据量的增加,性能差距会急剧拉大,这是因为遍历查找的时间复杂度为线性,而二分查找为对数。

快速对齐

函数一致可将数据按序列对齐,比如输入条件:=pOrderList=(10250、10247、10248、10249、10251),将订单明细按该列表对齐,求每个订单的金额小计。代码如下:


A1=连接(“demo") .query@x(“选择,从orderDetail" orderID、productID、价格、数量,)2=A1.align@a (pOrderList, orderID)格式(orderID ~。总和(价格*数量):小计)

但上述写法没有利用位置,性能因此不高。要想提高性能,可以将序列排序(手工建立索引表),再用二分法对齐,最后恢复为原顺序,代码如下:


A1=连接(“demo") .query@x(“选择,从orderDetail" orderID、productID、价格、数量,)2=最新=pOrderList.psort() 3=指数=pOrderList(详细的)4=A1.align@ab(指数,orderID)格式(orderID ~。sum(价格,*数量):总)5=A4.inv(最新)

就是:手工建立索引表。

A4:将订单明细表与订单列表对齐,求出金额小计。由于索引表有序,因此可用二分法对齐,即@b选项。

A5:将A4按原位置调整,与pOrderList的顺序保持一致。函数发票可按指定位置调整成员,这里按原位置调整成员,相当于恢复成原位置。

,

对利用位置前后的两种算法、模拟大访问量测试,可以看到性能提升显著:


现在AB8=()
9 A9=A1.align@a (A12, orderID)格式(orderID ~ .sum(价格*数量):总)10=interval@ms (A11,现在())/不利用位置,耗时43456毫秒11

12=现在()
13 A9=最新=A16.psort () 14
=指数=A16(最新)15
=A1.align@ab(指数,orderID)格式(orderID ~ .sum(价格*数量):总)16
=B18.inv(最新)17=interval@ms (A15,现在())/利用位置,耗时7313毫秒18=()
19 A9=A1.align@a (A12, orderID)格式(orderID ~ .sum(价格*数量):总)20=interval@ms (A11,现在())/不利用位置,耗时43456毫秒

有序数据批量查询

有时要对有序数据进行批量查询,比如pOrderList=(10877、10588、10611、11037、10685),请统计符合该列表的订单的运货费合计,代码可以这样写:

性能优化技巧——位置利用