实现报表数据的可控缓存

使用缓存可以提升报表性能是一个共识,一般高端报表工具都会提供报表缓存功能,将整个报表计算结果缓存在文件系统中,以便用户下次访问参数相同的报表时可以快速读取缓存结果进行展现。润乾报表作为报表工具的领军品牌,当然也具有这种常规的缓存功能。

但在有些情况下,报表开发人员还希望进一步控制缓存的内容,比如对于缓存内容,可能只想缓存一部分而不是整个报表结果,或者能够让其它报表或程序复用缓存内容,又比如对于超时设置,可能希望为不同的缓存结果设置不同的超时时间。这些需求都来自于实际业务中需要应对的数据量和实时性方面的不同情况,也是一般报表工具的缓存功能无法满足的。

润乾报表内置了可编程的数据计算引擎(结合集算器实现),允许开发人员灵活控制缓存内容,称为可控缓存。可控缓存能够带来更大的灵活性,下面就前面提到的三点展开介绍。

1、缓存部分结果

在报表开发中,有时并不希望将所有报表结果进行缓存,避免耗费过高的缓存成本(磁盘空间和应用服务器资源开销)。另外,当报表中的部分数据实时性要求很高,需要实时与数据库交互进行数据查询,那么就并不适合进行缓存。这种情况下,通过润乾报表的可控缓存可以将变化不太频繁的中间结果缓存起来。当报表再次请求时,实时性要求高的数据仍然从数据库中读取,同时结合缓存中的非实时数据进行报表计算,得到最终报表结果集。常规缓存方案中没有这种缓存部分结果的功能,只能设置整个报表是否进行缓存,这样报表在涉及数据的不同时效性时就必须平衡两者的矛盾,而润乾报表在这方面显然更加灵活,效率更高。

2、缓存结果复用

润乾报表中可控缓存是可以复用的,一个报表的缓存结果(部分或全部)可以被其他报表或程序读取并使用,而不必像常规报表缓存方案那样重复缓存同样的结果,这显然也会大幅度提高缓存的整体效率。当其他报表或程序使用某个报表的缓存结果时,只需从缓存(一般是磁盘文件)中读取,并与报表中其他数据来源(可能是 DB、文件,或是另一个报表的缓存)进行混合运算,就能得到报表需要的结果集,处理方式和缓存部分结果的方式类似。常规的报表缓存以报表模板为单位进行缓存,彼此无法复用,会造成相当的资源浪费,增加不小的性能开销,而润乾报表在这方面同样体现了灵活和高效。

3、设置不同超时时间

缓存机制中一定会有超时时间,过时的缓存会被清除,报表再访问时再重新缓存。一般报表工具的缓存超时时间在配置文件中设置,如通常的 3600s 或 7200s,这种设置往往作用于对单张报表的所有参数,有时甚至作用于所有报表。换句话说,整个报表甚至整个系统都必须使用同样的设置。

这种做法显然性能不高,如果能够针对不同的报表场景设置不同的超时时间,自然会更有效。比如,针对大量历史数据进行查询的报表,由于历史数据一般很少变化,我们希望报表的缓存结果可以保存较长时间,相应地设置较长的超时时间;而针对数据变化频繁,实时性要求较高的报表则设置较短的超时时间,以便满足数据的实时性要求。

润乾报表的结果缓存允许开发人员针对不同的报表设置不同的超时时间,以应对不同的报表场景。这种做法同样提供了更高的灵活性,使得报表缓存成为真正意义上的可控。

举例

可控缓存的具体实现可以参考润乾报表的相关文档资料,这里只是通过一个简单的例子说明一下结果缓存的使用方法:

首先使用润乾报表内置的集算器编写脚本生成和读取缓存文件,这个过程处于报表数据源的计算阶段。

A B C
1 E:\work\esProc\ / 缓存目录
2 =“sales_”+string(d_date) / 缓存文件名,报表名 + 参数 (dfxName_ParamName)
3 =file(A1+A2)
4 if A3.exists()&& interval@s(A3.date(),now())<3600 result A3.import@b() end
5 =connect(“demo”)
6 =A5.cursor(“SELECT 客户 ID,sum( 单价 * 数量) 订单总额 FROM 订单, 订单明细 WHERE 订单. 订单 ID= 订单明细. 订单 ID and year(订购日期)>? group by 客户 ID order by 订单总额 desc”,d_date)
7 =A6.fetch(5) >A5.close()
8 =A3.export@b(A7) / 生成缓存文件
9 return A7 / 为报表返回结果集

上述脚本首先指定缓存目录,并根据参数设置缓存文件名称,再根据文件名查找缓存文件是否存在(A4)。若存在且未超时则直接读缓存,否则直接连接数据库取数运算,并将计算结果生成缓存文件。

对比一下,如果报表中不使用缓存,那么脚本只需要这样编写:

A B
1 =connect(“demo”)
2 =A1.cursor(“SELECT 客户 ID,sum( 单价 * 数量) 订单总额 FROM 订单, 订单明细 WHERE 订单. 订单 ID= 订单明细. 订单 ID and year(订购日期)>? group by 客户 ID order by 订单总额 desc”,d_date)
3 =A2.fetch(5) >A1.close()
4 return A3

然后,只需要在润乾报表中调用上述集算脚本,编辑报表表达式就可以完成报表制作了。

需要注意的是,润乾报表的可控缓存也有其适用场景,并不能完全取代常规缓存。常规缓存手段会连同报表计算结果以及呈现属性一起保存,而这里的可控缓存只缓存数据,在呈现时还要再次进行外观计算,因此更适用于数据计算强度较高,外观计算强度较低的场景。实际应用中,两者可以结合使用。