什么是报表的数据库内中间冗余数据?

    绝大多数软件项目的数据库中,除了支撑系统运行的业务数据表(business table)之外,还有很多中间表(temporary table)。

    业务数据表是软件系统必须的基础数据表,是支持软件系统运行的持久化数据层,如销售管理系统中的部门、角色、权限、订单、客户、产品等等。报表中间表则是计算和生成报表的中间计算过程,中间表的名字经常是五花八门。

    按道理说,业务数据表应该是大部分,报表中间表只是小部分。但是,实际情况却恰恰相反。有些运行了较长时间的软件系统中,报表中间表达到几千个或者更多,而业务数据表只有一两百张。

    为什么数据库中会出现中间冗余数据?

    1、业务数据表结构的设计和报表要展现的数据之间有较大的差异,需要经过多步骤计算才能形成报表数据,每一步计算要把中间结果放在中间表中供下一步计算使用。

    2、业务数据表数据量较大,数据库计算报表的时间较长,只好先计算好报表数据,放到中间表中。

    3、计算报表的时候需要占用CPU、内存、硬盘IO等资源,会影响业务系统的正常运行,所以要夜间计算好报表数据,放到中间表中。

    为什么数据库中的中间冗余数据越来越多?删掉行不行?

    在项目建设阶段,需求边界的确定决定了系统功能,也就基本确定了业务数据表的数量,除非系统有结构性的修改,否则业务数据表的数量不会有特别大的变化。而在系统运行过程中,报表的个数随着时间而增加、报表需求也在不断变化,由此导致数据库中的报表中间表越来越多。

    甚至有些已经不再使用的报表删掉了,但是中间表却没有删掉。这不仅仅是因为忘记删掉,也可能是因为中间表互相依赖,形成了网状结构,已经没有人能够轻易地删掉了。老的不能删,新的不断建,报表中间表就越来越多,数据量越来越大。

    中间冗余数据有什么问题?

    关系型数据库的综合成本,是和数据表的数量、数据量相关的。数据库中充斥着各种报表中间表会存在下面的问题:

    1、数据表越多,数据量越大,数据库的负载压力越大,会造成性能的下降。

    2、数据库压力达到一定程度,数据库就必须扩容,项目成本会增加不少。

    3、数据库是扁平结构,不能以多级目录的形式来管理数据,只适合管理数量较少的表。中间表命名随意,形成大量意义混淆的表名,可管理性变差。

    4、表多、数据量大,会直接造成数据库管理和维护成本的增加。

    如何减少报表开发中的数据库内中间冗余数据?

    分库是解决数据库内中间冗余数据的办法之一,也是目前软件项目中常见的做法。但是,不管是将业务库分成多个,还是构建专门的数据仓库,本质上还是用传统关系型数据库来承载中间冗余数据,因此,上边所说的这些问题依然存在。

    那么,是否可以将中间冗余数据从数据库中移出来呢?小结果集直接计算后返回,大结果集放到硬盘文件上?这样做的好处非常明显:

    1、降低了数据库的压力,让业务系统运行更快。

    2、数据库不必因为报表中间表的原因扩容,降低了项目成本。

    3、文件可以按照业务种类、模块关系、时间顺序进行多级目录管理,可管理性较高。

    4、数据表少了,数据库管理和维护自然变得容易,降低了运维成本。

    但是,对于多数程序员来说,他们不是不愿意把中间表放到数据库外,而是不能放到库外,因为数据一旦离开了数据库,就失去了计算能力。例如:某项目中有个中间表temp2013kh-dingdan,是按照客户分组的2013年客户-订单数据。在数据库中,对这个表可以按照客户排序。但是一旦导出到文本文件中,文件本身是没有办法替程序员做排序的。

    用集算器esProc可以直接实现复杂计算并向报表工具返回结果集,同时还可以让文件了具备计算能力,实现程序员把报表中间数据从数据库中移出来的愿望。引入集算器之后的报表系统结构如下图:

esProc_report_redundance.jpg

    集算器封装了大量的结构和半结构化的数据计算类库,可以放在数据库和报表工具之间,形成报表计算层。

    对于计算非常复杂,需要分步骤计算的过程中产生的数据,如果数据量不大,内存能装下的话,集算器可以直接计算完返回给报表应用,不用制造中间表或者数据文件。

    对于必须保存的中间表,例如上边说的temp2013kh-dingdan,可以导出到文本文件(或者集算器的二进制文件)中,利用集算器的file和import函数导入进来,再利用集算器的sort函数完成排序。集算器提供了完备的类库,包括:分组、循环、排序、过滤、集合运算、有序计算等等。

    由于集算器支持异构的数据源,中间表temp2013kh-dingdan也可以和数据库中其他的业务表进行关联计算。例如,temp2013kh-dingdan中存的是客户编号,如果报表中需要展现的是客户名称的话,可以在集算器中对数据库中的客户表与文件中中间表进行关联计算。这就实现了移出数据库的中间表与没有移出数据库的统一计算。

    集算器部署非常简单,只需要引入一个jar包即可。同时,集算器为报表工具提供了友好的接口,报表可以通过jdbc来调用集算器的脚本,java代码示例如下:

    //建立连接

    Class.forName(“com.esproc.jdbc.InternalDriver”);

    con= DriverManager.getConnection(“jdbc:esproc:local://”);

    //调用存储过程,其中dfxName是dfx的文件名

    st =( com. esproc.jdbc.InternalCStatement)con.prepareCall(“calldfxName(?)“);

    //设置参数

    st.setObject(1,”3″);

    //执行存储过程

    st.execute();

    //获取结果集

    ResultSet set = st.getResultSet();

    值得一提的是,集算器提供功能强大的免费版本,一般的报表应用都可以很好的支持。程序员可以象引入其他Framework一样,逐步引入集算器,达到减少报表在数据库中的中间冗余数据的目的。