热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

存储过程实现报表数据源的利弊分析

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

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

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

一、 性能

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

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

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

这种情况下,存储过程的性能就表现的很差。其原因是大家常常忽略的:存储过程本身的过程控制代码解释执行的速度,要比SQL慢一个数量级,有些语句的执行速度甚至还会低于外部的Java程序。

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

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

二、 编程难度

存储过程是基于SQL的,所以SQL固有的一些问题,存储过程也没有办法避免:数据无序、缺乏集合、无法引用、分步不彻底。利用存储过程和SQL实现报表数据源计算需求的过程,事实上就是将业务问题翻译成存储过程和SQL语法的过程(类似小学生解应用题,将题目翻译成形式化的四则运算)。而SQL的模型体系很不符合人们的自然思维习惯,造成问题翻译的极大障碍,使得使用存储过程和SQL实现复杂数据计算的编程过程较为困难,所实现的代码也较难读懂、改写。

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

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

三、 代码管理

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

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

四、 系统维护

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

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

小结和展望

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

对于希望由存储过程解决的复杂数据源问题,可以考虑采用润乾公司开发的集算报表来实现,集算报表内置的开发语言集算器(esproc),相比存储过程而言,在多个方面都具备优势:

在性能方面,集算报表的esproc基于Java,代码解释执行的速度要快于存储过程自身的控制代码。esproc提供并行执行能力,可以充分利用普通计算机和PC服务器来实现分布式计算集群,可获得远远超过存储过程的性能。

如果业务允许,可以考虑将数据库中的报表相关数据移到文件系统中。esproc的文件访问和计算能力使得集算报表可以将数据文件作为数据源,充分发挥数据库和数据文件各自的优点,在有效降低数据库压力的同时,进一步提高集算报表的性能。

在编程难度方面,集算报表的esproc解决了SQL固有的问题,更接近人们的自然思维,可以更快速的写出报表数据计算程序,也非常容易读懂、维护。用esProc解决同样问题的代码长度要远远少于存储过程。

集算报表是跨平台和数据库的,非常容易移植,可以从多种数据库、文件中取数,统一进行计算。集算报表还提供功能强大的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的内容,直接展现到报表中。


推荐阅读
  • 收割机|篇幅_国内最牛逼的笔记,不接受反驳!!
    收割机|篇幅_国内最牛逼的笔记,不接受反驳!! ... [详细]
  • 尽管PHP是一种强大且灵活的Web开发语言,但开发者在使用过程中常会陷入一些典型的陷阱。本文旨在列出PHP开发中最为常见的10种错误,并提供相应的预防建议。 ... [详细]
  • 深入探讨ASP.NET中的OAuth、JWT与OpenID Connect
    本文作为前文关于OAuth2.0和使用.NET实现OAuth身份验证的补充,详细阐述了OAuth与JWT及OpenID Connect之间的关系和差异,旨在提供更全面的理解。 ... [详细]
  • 自SQL Server 2005以来,微软的这款数据库产品逐渐崭露头角,成为企业级应用中的佼佼者。本文将探讨SQL Server 2008的革新之处及其对企业级数据库市场的影响。 ... [详细]
  • 本文探讨了Java编程中MVC模式的优势与局限,以及如何利用Java开发一款基于鸟瞰视角的赛车游戏。 ... [详细]
  • 本文介绍了MySQL数据库的安全权限管理思想及其制度流程,涵盖从项目开发、数据库更新到日常运维等多个方面的详细流程控制,旨在通过严格的流程管理和权限控制,有效预防数据安全隐患。 ... [详细]
  • 免费获取:全面更新的Linux集群视频教程及配套资源
    本资源包含最新的Linux集群视频教程、详细的教学资料、实用的学习课件、完整的源代码及多种软件开发工具。百度网盘链接:https://pan.baidu.com/s/1roYoSM0jHqa3PrCfaaaqUQ,提取码:41py。关注我们的公众号,获取更多更新的技术教程。 ... [详细]
  • API网关作为微服务架构中的关键组件,扮演着系统与外部世界交互的唯一接口角色。它不仅封装了系统的内部复杂性,还为不同客户端提供了个性化的API接口。本文将探讨API网关的重要性及其核心功能。 ... [详细]
  • 本文介绍了Kettle资源库的基本概念、类型及其管理方法,同时探讨了Kettle的不同运行方式,包括图形界面、命令行以及API调用,并详细说明了日志记录的相关配置。 ... [详细]
  • 本文在前文基础上,进一步探讨了如何利用Multi-Paxos算法解决一系列值的共识问题。文中不仅分析了Basic Paxos的局限性,还详细阐述了通过引入领导者节点优化Multi-Paxos算法的具体方法。 ... [详细]
  • 2017成都物流技术创新峰会:深入探讨区块链应用
    2017年3月30日,第二届物流技术大会在成都成功举办,会上特别举办了关于区块链技术及其在物流行业应用的专题讨论,深入分析了区块链技术的发展历程、现状及未来趋势。 ... [详细]
  • Go 通过 Map/Filter/ForEach 等流式 API 高效处理数据
    go,通过,map,filter,foreach,等,流,式,ap ... [详细]
  • 本文详细介绍了如何使用递归方法对栈中的所有元素进行排序,确保从栈顶到底部的元素按升序排列。通过具体的代码示例,帮助读者理解栈排序的核心思想及实现步骤。 ... [详细]
  • 如何解决PHP中时间获取不准确的问题
    本文探讨了在PHP开发过程中遇到的时间获取错误问题,并提供了详细的解决方案,包括通过修改配置文件和编程方法来调整时区设置。 ... [详细]
  • 当我在命令行登录MySQL后,无法访问任何依赖数据库连接的PHP应用。此问题每次都会出现。以下是复现问题的具体步骤及解决方案。 ... [详细]
author-avatar
小嫣师妹
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有