如何用 esProc SPL 操作大 csv

 

esProc SPL 提供了游标运算,可以用非常简单的代码操作大 csv 文件,稍加改动就能变成并行计算,还有图形化界面,比 Pyhton 方便多了。
先去这里下载 esProc SPL:https://www.esproc.com/download-esproc/
懒得折腾源码的话可以用标准版,下载并安装。
准备好一个大 csv 文件:

Picture1png
打开 esProc IDE,新建脚本,在 A1 格写 SPL 代码,读取前 100 条:

=file("d:/OrdersBig.csv").cursor@tc().fetch(100)

函数 cursor 表示用游标打开文本文件,@表示函数的扩展选项,@t 表示首行为列名,@c 表示分隔符为逗号。
因为是大文件,全部读入内存可能溢出,所以只读 100 条看一下。
按 ctrl-F9 执行,可以在右边看到计算结果数据表。

Picture2png

SPL 代码写在单元格中,每个格执行后就会有个值,在右边可以看到,这会给调试带来很大的方便。

来试试计算,先数一下行数:


 A
1 =file("d:/OrdersBig.csv").cursor@tc()
2 =A1.skip()

函数 skip 用来跳过 N 条记录并返回跳过的记录数,参数为空时跳过全部记录。

Picture3png

共有 101,730,411 条记录。

再看看过滤,选出 Amount 在 3000 至 4000 之间,Client 含有 s 的记录:


 A
1 =file("d:/OrdersBig.csv").cursor@tc()
2 =A1.select(Amount>3000 && Amount<=4000 && like@c(Client,"*s*"))
3 =A1.fetch(100)

函数 select 用于条件过滤,函数 like 用于字符串匹配,* 是通配符,@c 表示不区分大小写。

因为可能结果还是很多,也只取前 100 条看看,执行结果在 A3:

Picture4png

排序也可以,比如按 OrderDate 的顺序、Amount 的逆序排序:


 A
1 =file("d:/OrdersBig.csv").cursor@tc()
2 =A1.sortx(OrderDate,-Amount)
3 =file("d:/result.csv").export@tc(A2)
4 =file("d:/result.csv").cursor@tc().fetch(100)

排序后把结果写入新文件,再打开新文件,取前 100 条。函数 sortx 用于大文件排序,- 表示逆序。

执行后看右边结果,已经排好序了。


Picture5png

再做些复杂的运算,分组汇总:


 A
1 =now()
2 =file("d:/OrdersBig.csv").cursor@tc(OrderDate,Client,SellerID,Amount)
3 =A2.select(year(OrderDate)>=2020 || !Client || to(101,400).contain(SellerID))
4 =A3.groups(year(OrderDate):y,month(OrderDate):m; sum(Amount):amt)
5 =output(interval@s(A1,now()))

SQL 程序员一定对 A4 的 groups 函数很熟悉,这里就不多说了。

A2 打开游标时只读要用到的列,可以提高速度。这里还增加了 A1 和 A5 来统计运行时间,并打印在控制台:

Picture6png

可以看到运行时间:145 秒。

并行计算可以充分利用现在的多核 CPU,必须试一试。把上面代码改成并行计算,只要在 cursor 函数后简单加个选项 @m,其余不变:


 A
1 =now()
2 =file("d:/OrdersBig.csv").cursor@tcm(OrderDate,Client,SellerID,Amount)
3 =A2.select(year(OrderDate)>=2020 || !Client || to(101,400).contain(SellerID))
4 =A3.groups(year(OrderDate):y,month(OrderDate):m; sum(Amount):amt)
5 =output(interval@s(A1,now()))

@m 表示按照 option 里配置的并行选项进行多线程计算。

同时把这个并行选项打开。

Picture7png
现在执行一遍:

Picture8png
提升到了 92 秒,可能受到硬盘的并发限制,做不到倍数性能提升,用 2 线程跑的结果也差不多。

上面是几个基本运算,官网上对大 csv 计算的例子更加广泛深入,代码也都很简单,值得一看。