在报表项目中,当数据计算较为复杂的时候,报表开发者可能会考虑是否用存储过程来实现报表数据源准备。
这里,我们从几个不同的方面来看一下。用存储过程来实现报表数据源计算的利和弊。
一、 性能
说到存储过程的长处,性能是最常被提及的。存储过程进行报表数据计算的时候。不须要将数据取出数据库,会获得较高的性能。其主要原因是数据库IO通道(比如:JDBC)效率一向非常差,大量数据取出来非常费时间。
即便如此。这个问题还是要深入分析的:
1、写在存储过程中的SQL语句是预先编译的。因此比外部程序提交的SQL要快一些。可是。非常多情况下,报表的数据计算逻辑过于复杂,非常难用单个或者多个SQL来实现。程序猿须要利用存储过程的过程控制语句来实现。比如,常见的通过循环遍历数据来实现复杂计算的做法。
这样的情况下,存储过程的性能就表现的非常差。
其原因是大家经常忽略的:存储过程本身的过程控制代码解释运行的速度,要比SQL慢一个数量级,有些语句的运行速度甚至还会低于外部的Java程序。
2、存储过程中能够写多个SQL来实现分步计算,可是每一步SQL运行的中间结果难以复用,因此可能会一份数据反复复制多次。算多次。减少性能。存储到暂时表尽管能够达到复用目的,但会造成外存訪问导致性能更差。
3、存储过程势必添加数据库的计算负载和空间占用,尽管理论上说能够通过数据库扩容来维持性能和容量,可是数据库的扩容成本毕竟比应用server高非常多。
因此,非常多项目仅仅好在一段时间内容忍数据库的性能减少。
二、 编程难度
存储过程是基于SQL的,所以SQL固有的一些问题。存储过程也没有办法避免:数据无序、缺乏集合、无法引用、分步不彻底。利用存储过程和SQL实现报表数据源计算需求的过程。其实就是将业务问题翻译成存储过程和SQL语法的过程(类似小学生解应用题,将题目翻译成形式化的四则运算)。而SQL的模型体系非常不符合人们的自然思维习惯,造成问题翻译的极大障碍,使得使用存储过程和SQL实现复杂数据计算的编程过程较为困难。所实现的代码也较难读懂、改写。
存储过程的还有一个弊端是不易移植。和SQL相当的标准化不同,存储过程用到的过程控制语法通常是不同厂家的数据库特有的,换了数据库基本上没法运行。假设报表项目须要訪问多个不同种类的数据库,更是存储过程无法实现的。
同一时候。由于缺乏非常好的开发工具,所以存储过程编程和调试相对照较困难。
三、 代码管理
数据库中的存储过程提供了“包”的概念,对大量存储过程进行归类。可是除此之外,再无其他分类管理办法。而包仅仅支持一层的分类,所以对于数量庞大的存储过程来说,easy造成管理混乱。
在这种情况下。应该用“树”这种多层分类管理代码。
存储过程还有一个特点是比較有争议的:在生产环境下。能够通过直接改动存储过程的方式改动报表的数据计算逻辑,而不用重新启动server。
但这个“长处”同一时候也带来非常大的弊端:有人直接就在正式server上改动存储过程。而没有经过完整的測试,程序正确性无法保证,代码管理也变得混乱。
四、 系统维护
存储过程须要编译才干使用,改动报表数据计算算法时要DBA的配合,须要数据库的写权限,添加安全风险。
存储过程须要预编译。假设带有引用关系的对象发生改变时,受影响的存储过程将须要又一次编译,添加维护工作量。
小结和展望
经过上述分析,我们觉得写存储过程来实现报表复杂数据计算整体来讲是弊大于利的。普通情况下不建议这样做,实在由于数据量导致的性能问题须要用。也要尽量把应用范围压到最小。
对于希望由存储过程解决的复杂数据源问题,能够考虑採用润乾公司开发的集算报表来实现,集算报表内置的开发语言集算器(esproc)。相比存储过程而言,在多个方面都具备优势:
在性能方面。集算报表的esproc基于Java,代码解释运行的速度要快于存储过程自身的控制代码。esproc提供并行运行能力,能够充分利用普通计算机和PCserver来实现分布式计算集群,可获得远远超过存储过程的性能。
假设业务同意,能够考虑将数据库中的报表相关数据移到文件系统中。
esproc的文件訪问和计算能力使得集算报表能够将数据文件作为数据源,充分发挥数据库和数据文件各自的长处,在有效减少数据库压力的同一时候。进一步提高集算报表的性能。
在编程难度方面,集算报表的esproc攻克了SQL固有的问题,更接近人们的自然思维,能够更高速的写出报表数据计算程序,也很easy读懂、维护。用esProc解决相同问题的代码长度要远远少于存储过程。
集算报表是跨平台和数据库的。很easy移植,能够从多种数据库、文件里取数,统一进行计算。集算报表还提供功能强大的esproc集成开发环境(IDE),减少编程工作量,提高代码调试的效率。
在代码管理方面,集算报表的程序文件(dfx文件)能够在操作系统中形成树形的结构,形成多层分类管理。
集算报表的程序文件能够和Java文件一样进行主要的配置管理。假设须要的话,能够导出成文本文件进行更仔细的版本号管理。
在系统维护方面,集算报表是在应用服务层执行的。程序修改无需数据库权限,不会带来数据安全上的问题。
集算报表的esproc程序之间是通过函数的方式调用的,仅仅要函数的接口不变,函数内部的变化不会影响报表本身或者其它esproc程序。
最后。我们通过一个详细的样例。来看一下用集算报表的esproc和oracle的存储过程分别实现同样数据源计算的代码对照:
某电信产品厂商有一张报表,主要目的是分析优势产品的销售额、销量、环比等指标,当中优势产品的定义是”在每一个州的销量均在前10名的产品”,数据主要存储在stateSales table。其数据结构例如以下:
用Oracle存储过程
01 create or replace package salesPkg 02 as 03 type salesCur is ref cursor; 04 end; 05 CREATE OR REPLACE PROCEDURE topPro(io_cursor OUT salesPkg.salesCur) 06 is 07 varSql varchar2(2000); 08 tb_count integer; 09 BEGIN 10 select count(*) into tb_count from dba_tables where table_name='TOPPROTMP'; 11 if tb_count=0 then 12 strCreate:='CREATE GLOBAL TEMPORARY TABLE TOPPROTMP ( stateTmp NUMBER not null, productTmp varchar2(10) not null, amountTmp NUMBER not null ) ON COMMIT PRESERVE ROWS'; 13 execute immediate strCreate; 14 end if; 15 execute immediate 'truncate table TOPPROTMP'; 16 insert into TOPPROTMP(stateTmp,productTmp,amountTmp) select state,product,amount from stateSales a where not( (a.state,a.product) in ( select state,product from stateSales group by state,product having count(*) > 1 ) and rowid not in ( select min(rowid) from stateSales group by state,product having count(*)>1 ) ) order by state,product; 17 OPEN io_cursor for 18 SELECT productTmp FROM ( SELECT stateTmp,productTmp,amountTmp,rankorder FROM (SELECT stateTmp,productTmp,amountTmp,RANK() OVER(PARTITION BY stateTmp ORDER BY amountTmp DESC) rankorder FROM TOPPROTMP ) WHERE rankorder<=10 order by stateTmp ) GROUP BY productTmp HAVING COUNT(*)=(SELECT COUNT(DISTINCT stateTmp ) FROM TOPPROTMP); END;
用esProc:
集算报表能够通过集算器数据集方便的接收A5的内容。直接展现到报表中。