润乾报表性能优化思路总结(部分)

由于性能的概念比较宽泛,故本文中提到的性能问题只是狭义地指报表各种“慢”的情况。
本文将多种“慢”的情况加以归纳,分析可能出现的原因,提供对应的调优策略。由于本文开篇提到的原因,本文只总结了如下方面,性能方面的问题以及解决办法会慢慢添加、逐步完善。
1 报表展现慢
对于展现慢的问题,我们首先要判断问题是出在报表端,还是非报表端。测试可以通过:a、减小并发量,若到一定程度问题不再出现,则说明是非报表原因;若并发数减小到 1,问题仍存在,转 b;
b、将报表数据集内建,若问题仍存在说明是报表原因;否则为非报表原因;
1.1 报表原因
问题若出现在报表端,可以考虑进行如下优化:
1.1.1 优化 SQL 语句
SQL 语句书写不当经常会引发效率问题,将客户数据集 sql 拷贝到数据库客户端执行,若执行速度缓慢,说明 sql 写法有待检查。Sql 语句书写原则比如少用 in 操作符、不要用 not in 操作符、用“>=”替代“>”等,详细的 sql 优化策略可以参考:http://mihuxiaozhu.javaeye.com/blog/210401
比较复杂的 sql 可以使用存储过程替代。
还可以使用 sql 优化工具,如:tkprof ,explain plan,autotrace,toad。
另外,在数据集 sql 语句中使用 order by 函数排序也尤为重要(若报表中存在较多的结果排序情况)。
1.1.2 减少数据集个数
数据集的数量也会导致效率问题,所以报表设计的时候应该尽量将需要的数据放到一个或几个数据集中取,而不是多个,尽量做到数据复用。
1.1.3 精简报表表达式
虽然润乾报表提供的函数都较为高效,但有时客户书写的报表表达式不是很简洁,像这样的判断语句:if(ds2.select1(num)>0,ds2.select(num),0),我们完全可以将 ds2.select1(num) 放到其他单元格中,使用的时候直接饮用该单元格就可以了。一旦类似这样的表达式大量使用,势必会影响报表运行效率,所以我们一定要秉承使用效率最高表达式的原则。
1.1.4 使用分页标签
对于大数据量的报表,建议客户使用分页标签进行分页,效率会得到很大提升。分页标签介绍以及使用见教程。
1.1.5 增加过滤条件
对于需要一页展现大量数据的报表,可以使用参数模板,通过参数过滤掉部分数据,此方法建议不分页大数据量报表使用。
尤其在 sql 中有? is null 的情况,可以通过宏处理一下 sql。
1.1.6 检查自动计算
有时填报表展现慢是由于自动计算引起的,曾经有一个客户的报表有 10 个自动计算表达式,每个单元格要扩展出来 1300 行,这样就要运算 10*1300 个 js 函数,速度肯定慢。有些自动计算表达式完全可以通过单元格表达式实现,所以对于填报表展现慢,我们要注意自动计算的问题。
1.1.7 配置 reportConfig.xml 文件
有时我们还需要检查 reportConfig.xml 配置文件,看客户的配置是否未启用缓存、同时计算的报表个数过少、等待时间过长等。
缓存配置:
cachedReportDir
E:\work\report\cached
cachedIdPrefix
A
cachedReportTimeout
30
alwaysReloadDefine
yes

若客户报表应用未启用缓存,可能会导致报表展现缓慢的问题。

计算报表配置:
maxCellNum
  
maxConcurrentForReport
9999
  
maxWaitForReport
9999
  
maxWaitTimeForReport
9999

若客户配置同时计算的报表数过小,等待时间过长,这样也会出现“慢”的问题。

以上情况可以通过直接向客户询问以及查看 reportConfig.xml 文件确定。
1.2 非报表原因
1.2.1 数据库连接数用尽
数据库连接数用尽后,应用请求的数据库连接会在等待时间内一直等待(与 webServer 设置有关),而呈现给用户的现象就是报表很久都不显示。
判断数据库连接数是否用尽可以采用如下方法:
a. 使用与报表无关的数据库工具,连接该数据库,连通后退出;
b. 启动报表应用,重现该问题;
c. 使用 a 中调通的工具连接数据库,若连不通,证明数据库连接数用尽;若可以连通说明不是连接数引起的,需进行其他操作排查。
如果是由于数据库连接数用尽引起的报表展现慢的问题,建议客户增大连接数。Oracle 数据库端的配置可以参考:http://blog.sina.com.cn/s/blog_4979b49e0100glz1.htmlhttp://wallimn.javaeye.com/blog/482523,其他数据库配置可以在网上搜索,本文后续后逐渐增加各类数据库的配置方法。
1.2.2 应用服务器连接数用尽
应用服务器连接数用尽,会出现报表应用访问慢的情况。测试是否是该原因导致可以通过如下方法:
a. 准备一个与报表应用无关的 jsp,可以成功访问 webServer,准备好后关闭连接;
b. 启动报表应用,重现该问题;
c. 使用 a 中准备的 jsp 访问 webServer,若不可以访问,则说明 webServer 的连接数用尽;否则需继续排查。
tomcat 连接数等相关配置可以参考:http://blog.csdn.net/srjthinker/archive/2008/07/14/2646838.aspx,其他 webServer 的配置详情会后续添加。
1.2.3 应用服务器 JVM 内存用尽
判断是否是 jvm 内存用尽导致的问题,可用通过查看问题发生时 jvm 使用情况判定。不同 webServer 查看和修改方式有所不同,本文以 tomcat6 为例,其他类似 webServer 将后续添加,具体步骤如下:
a. 修改 tomcat-6.0.29\conf 下 tomcat-users.xml 文件,添加
  
                                                                                      
  
  
  
  
    
b. 启动 tomcat,访问http://localhost:8080(需要修改成自己的)进入 tomcat 主页面
c. 点击左侧的 Tomcat Manager,输入 admin/tomcat 即可进入 manager 界面
d. 点击右上角的 Server Status,即可查看当前 JVM 内衬使用情况,如图:

JVM 内存设置方法见:http://jetway.javaeye.com/blog/106946
1.2.4 服务器内存用尽
还有服务器物理内存用尽的情况,一般这种情况客户可以比较容易查看到,当然我们也要注意这种情况的排查方法:
a. 报表应用启动前记录内存使用情况,包括内存总大小,当前使用量;
b. 启动报表应用,重现问题,且问题出现总是发生在内存占满(达到一个极高值)的时候,说明问题是由于物理内存用尽导致的。
1.2.5 服务器 cup 资源用尽
Cup 资源用尽的排查办法同内存用尽:
a. 报表应用启动前记录服务器 cpu 资源使用情况,可是使用任务管理器等 cup 监控程序;
b. 报表应用启动,重现问题,若问题出现总是在 cup 资源使用率为 100% 的时候,则该问题是由于 cup 资源占满引起的。
此时需要客户处调整资源分配,解决该问题。

2 报表导出慢
报表导出慢多见于大数据量导出 Excel 操作,对于一些其他小数据量导出 Excel 慢的问题多半会伴随出现异常信息,我们根据异常排查即可。本机只对大数据量导出慢给出几个解决办法。
2.1 单个报表导出慢
一般大数据量单个报表导出 Excel 慢的情况,可以考虑使用如下方式处理
2.1.1 拆分数据
通过参数控制每次导出的数据量,多次进行导出操作。
2.1.2 分片导出
复杂报表拆分成多个报表后,一次导出。
2.1.3 通过 API 导出
参考郑重做过的《导出 Excel 问题专项汇总》,里面介绍了海量数据到 Excel 的办法。

2.2 大量报表导出慢
有的客户在一次性导出大量报表的时候出现导出慢的情况,一般这种情况是由于工作时间用户都在使用系统并占用了大量的系统资源,影响导出的速度。出现这种情况建议客户将导出 Excel 的操作放到非工作时间进行,如下班后。这就需要
2.2.3 使用调度器
调度器可以配置定时任务执行诸如导出 Excel 的操作,详情见调度器文档。

3 填报慢
一般出现填报慢的问题,多半也都是由于数据量大引起的,我们可以采用如下方式缓解
3.1 分片填报
将复杂的填报表拆分成多个报表,分别进行填报。
3.2 直接填报
大量的校验表达式有时会拖慢填报速度,这时可以考虑不经过校验直接进行填报。
3.3 使用行式填报
由于行式填报表的效率要高于普通填报表,在能转行式的情况下可以转为行式填报表进行填报。
3.4 代码填报
对于业务逻辑比较复杂的情况,可以采用写程序进行填报,如报表提供的填报更新类,使得填报表的提交过程中可以实现内部的一些业务逻辑,比如提交数据非空时才允许更新数据库等,详细介绍及使用见教程。

4 报表打印慢
打印慢问题多见于大报表打印慢,可以采用如下方法
4.1 使用分页标签
分页标签除了对于报表展现作用极大以外,对于打印也有作用,若客户出现报表展现和打印比较慢的情况,可以使用分页标签。
4.2 使用大报表打印
大数据量报表打印可以采用润乾提供的“大数据量报表 applet 打印”的功能。
4.2.1 介绍
1、 打印窗口显示时,先向服务器申请第一页,并显示第一页。
2、 在预览窗口按下一页或最后页按钮时,如果此页还没有从服务器取过来,那么先将之取过来并显示。
3、 在打印窗口中依然可以改变页面设置、分栏数、缩放打印等,让服务器重新分页,并传第一页来显示。
4、 在按打印按钮时,弹出一个新窗口,此窗口中可以选择打印机、设置要打印的页、显示打印进度、停止打印或退出。
为了避免内存溢出,采取每 5 页为一个打印单位发送给打印机,这 5 页打印完后就将从内存中清除。
4.2.2 使用方法
1、在 web.xml 中配置后台分页传输的服务,如下
    com.runqian.report4.view.PagedPrint
    com.runqian.report4.view.PagedPrint
  
  
    com.runqian.report4.view.PagedPrint
    /servlet/pagedPrintServer
  

2、htmlTag 中增加一个属性:serverPagedPrint=“yes”
该属性的含义是:applet 打印时是否采用服务器分页后再按页传输的方式,值为 yes 或 no。