在报表项目中,当数据计算较为复杂的时候,报表开发人员可能会考虑是否用存储过程来实现报表数据源准备。这里,我们从几个不同的方面来看一下,用存储过程来实现报表数据源计算的利和弊。

一、性能

说到存储过程的优点,性能是最常被提及的。存储过程进行报表数据计算的时候,不需要将数据取出数据库,会获得较高的性能,这是因为数据库IO通道(如JDBC)效率低,大量数据取出来很费时。

即便如此,这个问题还是要深入分析的:

1、写在存储过程中的SQL语句是预先编译的,因此比外部程序提交的SQL要快。但很多时候报表的计算逻辑过于复杂,很难用单个或者多个SQL来实现。程序员需要利用存储过程的过程控制语句来实现,比如通过循环来遍历数据。

这种情况下存储过程的性能是比较差的,因为存储过程本身的过程控制代码解释执行的速度,比SQL慢一个数量级,有些语句的执行速度甚至还会低于外部的Java程序。

2、存储过程可以写多个SQL来实现分步计算,但是每一步SQL的中间结果难以复用,导致一份数据算多次,复制多次,从而降低性能。虽然可以使用临时表达到数据复用的目的,但会造成外存访问以致性能更差。

3、存储过程势必增加数据库的计算负载和空间占用,理论上可以通过扩容来维持性能和容量,但是数据库的扩容成本毕竟比应用服务器高很多。因此,很多项目只好在一段时间内容忍数据库的性能降低。

二、编程难度

存储过程是基于SQL的,所以SQL固有的一些问题,存储过程也没有办法避免:数据无序、缺乏集合、无法引用、分步不彻底。利用存储过程和SQL实现报表数据源计算的过程,就是将业务翻译成存储过程和SQL语法的过程(类似小学生解应用题,将题目翻译成形式化的四则运算)。

SQL的模型体系很不符合人们的自然思维习惯,造成问题翻译的极大障碍,编程过程较为困难,实现的代码也较难读懂、改写。

存储过程的另一个弊端是不易移植。和SQL的标准化不同,存储过程用到的过程控制语法是不同厂家的数据库特有的,换了数据库基本上没法执行。如果报表项目需要访问多个不同种类的数据库,更是存储过程无法实现的。

同时,因为缺乏很好的开发工具,所以存储过程编程和调试相对比较困难。

三、代码管理

数据库中的存储过程提供了“包”的概念,对大量存储过程进行归类。但是除此之外,再无其它分类管理办法。而包只支持一层的分类,所以对于数量庞大的存储过程来说,容易造成管理混乱。在这种情况下,应该用“树”这样的多层分类管理代码。

存储过程另一个特点是比较有争议的:在生产环境下,可以通过直接修改存储过程的方式修改报表的数据计算逻辑,而不用重启服务器。但这个“优点”同时也带来很大的弊端:有人直接就在正式服务器上修改存储过程,而没有经过完整的测试,程序正确性无法保证,代码管理也变得混乱。

系统维护

存储过程需要编译才能使用,修改报表数据算法时要DBA的配合,需要数据库的写权限,增加安全风险。

存储过程需要预编译,如果带有引用关系的对象发生改变时,受影响的存储过程将需要重新编译,增加维护工作量。

小结和展望

经过上述分析,我们认为写存储过程来实现报表复杂数据计算总体来讲是弊大于利的。一般情况下不建议这样做,实在因为数据量导致的性能问题需要用,也要尽量把应用范围压到最小.