【性能优化】2.5 [外存数据集] 有序及数据追加
2.5 有序及数据追加
即使不减少存储量,有序存储对于查找和遍历也有巨大的意义,我们会后面会逐步讲到如何利用有序提高运算性能。
A |
|
1 |
=file("data.ctx").create(#ID,…) |
2 |
=file("data1.ctx").create(#K1,#K2,…) |
创建组表时,参数中的字段名前面加了 #,即表明该组表将对这些字段有序(按字段的次序,且必须是前几个字段)。不过,SPL 在 append 时并不检查,需要程序员自己保证写入数据确实是有序的。
有序存储的麻烦主要在于数据追加,新增数据不一定总是能有序地接到原有数据后面。比如组表当前数据是按 ID 字段排序的,而新增数据中的 ID 字段通常还是同一批值,要保证整个组表对 ID 有序,原则上需要把所有数据全部重新按 ID 排序,不能简单地用追加方式写到后面。而大数据排序是个非常耗时的动作。
不过,好在原有的大量数据已经有序,只要将新增的数据排序后,可使用低成本的有序归并算法和原有数据合并。相当于把所有数据读写一遍,避免常规大排序中产生很多临时文件的现象,从而较快速地得到一份全有序的数据。
A |
|
1 |
=file("data.ctx").open() |
2 |
=file("data_new.ctx") |
3 |
>A1.create(A2) |
4 |
=A1.cursor() |
5 |
=A2.open() |
6 |
=file("data_append.btx").cursor@b() |
7 |
>A5.append([A4,A6].merge()) |
这个动作可以简写为
A |
|
1 |
=file("data.ctx") |
2 |
=file("data_new.ctx") |
3 |
=file("data_append.btx").cursor@b() |
4 |
>A1.reset(A2;A3) |
或者直接归并到原文件上
A |
|
1 |
=file("data.ctx") |
2 |
=file("data_append.btx").cursor@b() |
3 |
>A1.open().append@m(A2) |
对于大数据来讲,全部读写一遍也是相当耗时的。这时候可以采用双文件的方式,用两个文件来存储,一个存储较大数量的历史数据,一个存储近期新增的数据。追加数据时,一般只和后者归并,积累一段时间后再做全量归并。
A |
B |
|
1 |
=file("data_history.ctx").open() |
|
2 |
=file("data_recent.ctx") |
|
3 |
=file("data_new.btx").cursor@b() |
|
4 |
if (day(now())==1 |
>A1.append@m(A2.open().cursor()) |
5 |
>A1.create@y(A2) |
|
6 |
>A2.open().append@m(A3) |
由上面的代码例子可以看出来,当日期为 1 号时将把历史数据和近期数据合并,其它日期则只在近期数据库归并新增数据。如果每天对新增数据执行一次这样的追加动作,近期数据文件中最多会存储一个月的数据,历史数据文件则会存储一个月之前的所有数据。也就是说,历史数据文件可能很大,近期数据文件相对小。这样,每天的归并量都不会很大,能够较快地完成数据追加,而每个月才消耗较多时间执行一次全量数据的整理工作。
使用两个文件后,访问组表获取数据时,需要分别从历史数据文件和近期数据文件中读取再做归并后返回,以保证返回整个结果集仍然有序:
A |
|
1 |
=file(“data_history.ctx”).open().cursor() |
2 |
=file(“data_recent.ctx”).open().cursor() |
3 |
=[A1,A2].merge(…) |
因为需要在访问时时行归并,两个文件时读取性能会比单个文件时下降一点。
这个写法有些复杂,在有了复组表概念后,SPL 可以简化这个写法。
请问文章倒数第二块代码中,B5 格子中的 A1 是组表文件,是不是要先 open 成实表,才能把其数据结构复制给 A2 表示的组文件:
因为用组表文件创建时,函数使用是这样的:file.create@y(字段名)。
另外,根据函数文档 append@m 有 @m 选项时,要求 "组表文件没有在其他地方打开"。所以以上截图中的 B4 和 A6 符合文档说明。
但文章倒数第 3 块代码中的 A3 格子写成了 A1.open().append@m(cs), 如下:
所以在用 append@m 时,“组表文件没有在其他地方打开”,这个其他地方是指何处?
以上问题恳请大佬得闲时给予指导解惑,谢谢!!
这个是改版时的笔误,在 A1 要把它打开。
“其它地方那句话”应该也是改版时的遗留。组表整个都不能并发写,无论什么选项都不可以。
其他地方 指的是任何其它执行 open 的地方,比如前面执行了 open() 的单元格,另一个打开的 splx,或者另一个 IDE 都有可能。
谢谢老贼,谢谢 liwei 大佬🙏
组表是 SPL 特有的存储方式 (文件格式),涉及到的内容有点繁杂,诸如基表,附表,实表,虚表,复组表…以及对应的各种方法,一时难以捋顺。论坛也有很多关于数据迁移和转存组表的文章,可见组表的重要性。我目前没有项目实操经验,所有的认知都仅限于官网的文章,就拿组表数据的追加更新来说,目前了解到的方法有三种:1、append 2、update 3、reset。在我外行人看来,这 3 种方法的最终结果是把原有的冷数据追加(更新) 了部分数据,实现了增量更新,不过是殊途同归,但其中涉及到的原理肯定有差别,非常希望有文章能系统地阐述一下这 3 种方法的区别,适用于什么样的场景,有啥讲究。或者说,针对组表,出系列文章,从最基础的组表文件的生成和基础数据的追加,到冷热数据的增删改,再到索引的创建和运用,…等等(论坛有这方面的文章,但分布零散),不过这不是说话打字那么轻松,需要花点心思,也是额外的工作量,大佬们都有正事要忙,我自己再捋捋组表这一块关键内容。
Have a nice day!