由于性能的概念比较宽泛,故本文中提到的性能问题只是狭义地指报表各种“慢”的情况。
本文将多种“慢”的情况加以归纳,分析可能出现的原因,提供对应的调优策略。由于本文开篇提到的原因,本文只总结了如下方面,性能方面的问题以及解决办法会慢慢添加、逐步完善。
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配置文件,看客户的配置是否未启用缓存、同时计算的报表个数过少、等待时间过长等。
缓存配置:
<config><!--缓存文件夹-->
<name>cachedReportDir</name>
<value>E:\work\report\cached</value>
</config>
<config><!--报表缓存的前缀,只有在集群环境中并且多台服务器共享一个报表缓存目录时才需要设置-->
<name>cachedIdPrefix</name>
<value>A</value>
</config>
<config><!--报表缓存保存的时间,以分钟为单位-->
<name>cachedReportTimeout</name>
<value>30</value>
</config>
<config><!--是否每次都重新读取报表定义,正式上线应设置为no-->
<name>alwaysReloadDefine</name>
<value>yes</value>
</config>
若客户报表应用未启用缓存,可能会导致报表展现缓慢的问题。
计算报表配置:
<config> <!--当前报表系统能运算的最大单元格数,能够动态控制并发数-->
<name>maxCellNum</name>
<value></value>
</config>
<config> <!--表示报表WEB应用中服务器可以同时计算的报表的个数-->
<name>maxConcurrentForReport</name>
<value>9999</value>
</config>
<config> <!--报表WEB应用中服务器可以等待计算的报表的个数-->
<name>maxWaitForReport</name>
<value>9999</value>
</config>
<config> <!--表示内存溢出后,最长等待多久才允许新任务访问,以秒为单位-->
<name>maxWaitTimeForReport</name>
<value>9999</value>
</config>
若客户配置同时计算的报表数过小,等待时间过长,这样也会出现“慢”的问题。
以上情况可以通过直接向客户询问以及查看reportConfig.xml文件确定。
1.2非报表原因
1.2.1数据库连接数用尽
数据库连接数用尽后,应用请求的数据库连接会在等待时间内一直等待(与webServer设置有关),而呈现给用户的现象就是报表很久都不显示。
判断数据库连接数是否用尽可以采用如下方法:
a. 使用与报表无关的数据库工具,连接该数据库,连通后退出;
b. 启动报表应用,重现该问题;
c. 使用a中调通的工具连接数据库,若连不通,证明数据库连接数用尽;若可以连通说明不是连接数引起的,需进行其他操作排查。
如果是由于数据库连接数用尽引起的报表展现慢的问题,建议客户增大连接数。Oracle数据库端的配置可以参考:http://blog.sina.com.cn/s/blog_4979b49e0100glz1.html 和http://wallimn.javaeye.com/blog/482523,其他数据库配置可以在网上搜索,本文后续后逐渐增加各类数据库的配置方法。
1.2.2应用服务器连接数用尽
应用服务器连接数用尽,会出现报表应用访问慢的情况。测试是否是该原因导致可以通过如下方法:
a. 准备一个与报表应用无关的jsp,可以成功访问webServer,准备好后关闭连接;
b. 启动报表应用,重现该问题;
c. 使用a中准备的jsp访问webServer,若不可以访问,则说明webServer的连接数用尽;否则需继续排查。
tomcat连接数等相关配置可以参考:http://blog.youkuaiyun.com/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文件,添加
<role rolename="tomcat"/>
<role rolename="role1"/>
<role rolename="manager"/>
<role rolename="admin"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
<user username="admin" password="tomcat" roles="admin,manager"/>
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中配置后台分页传输的服务,如下
<servlet>
<servlet-name>com.runqian.report4.view.PagedPrint</servlet-name>
<servlet-class>com.runqian.report4.view.PagedPrint</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>com.runqian.report4.view.PagedPrint</servlet-name>
<url-pattern>/servlet/pagedPrintServer</url-pattern>
</servlet-mapping>
2、htmlTag中增加一个属性:serverPagedPrint="yes"
该属性的含义是:applet打印时是否采用服务器分页后再按页传输的方式,值为yes或no。