【性能优化】4.5 [遍历技术] 多路游标
4.5 多路游标
使用 fork 可以灵活地实现并行计算,但代码仍然略显繁琐,特别是对于很常见的单数据表的统计,而且还要注意再次汇总线程返回结果时可能要改变函数(从 count 变 sum)。SPL 提供了更简单的多路游标语法,可以直接生成并行游标。
A |
|
1 |
=file("orders.txt") |
2 |
=A1.cursor@tm(area,amount;4) |
3 |
=A2.groups(area;sum(amount):amount) |
4 |
=A1.cursor@tm(area,amount;4) |
5 |
=A4.select(amount>=50).groups(area;count(1):quantity) |
使用 @m 选项即可创建多路并行游标,然后和之前的单路游标使用方法一样,SPL 会自动处理并行以及将结果再汇总的动作,会自动正确处理第二轮该用的函数。
多路游标上也可以使用管道实现遍历复用:
A |
B |
|
1 |
=file("orders.txt").cursor@tm(area,amount;4) |
|
2 |
cursor A1 |
=A2.groups(area;sum(amount):amount) |
3 |
cursor |
=A3.select(amount>=50).groups(area;count(1):quantity) |
多文件的游标也能拼成多路游标做并行计算:
A |
|
1 |
=12.(file("orders"\~\".txt").cursor@t(area,amount)) |
2 |
=A1.mcursor() |
3 |
=A2.select(amount>=50).groups(area;count(1):quantity) |
还可以在内存序表上建立内存多路游标,利用并行技术提高运算性能。
A |
|
1 |
=file("orders.txt").import@t() |
2 |
=A1.cursor@m(4) |
3 |
=A2.groups(area;sum(amount):amount) |
对于 CPU 强和硬盘弱的场景,我们还可以单路游标转换成多路游标,也就是游标取数时使用单路,避免硬盘的并行,但计算时再使用多路,利用多 CPU 来提高性能,适合于文本文件这类需要较多 CPU 来解析的情况。
A |
|
1 |
=file("orders.txt").cursor@t(area,amount) |
2 |
=A1.mcursor(4) |
3 |
=A2.groups(area;sum(amount):amount) |
多路游标上的汇总运算需要进行第二轮(每一路的计算结果要再次汇总),二次汇总的计算逻辑可能还不一样,从上面的例子上可以看出,SPL 把常见运算已经实现了,所以直接把多路标当成单路游标运算就可以了。但如果碰到非常见运算,还有必要自己做第二轮。
A |
B |
|
1 |
=file("orders.txt").cursor@tm(area,amount;4) |
|
2 |
fork A1 |
return A2.groups(area;count(1):C) |
3 |
=A2.conj().groups(area;sum(C):C) |
这里用 count 举例(事实上 count 已经被 SPL 处理过了)。SPL 对于多路游标还提供了一种简化的 fork 语法,允许并行多路游标的每一路。