【性能优化】2.5 [外存数据集] 有序及数据追加

 

【性能优化】2.4 [外存数据集] 组表与列存

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 可以简化这个写法。

【性能优化】2.6 [外存数据集] 数据更新及复组表
【性能优化】 前言及目录