润乾报表优化与性能管理.docx_第1页
润乾报表优化与性能管理.docx_第2页
润乾报表优化与性能管理.docx_第3页
润乾报表优化与性能管理.docx_第4页
润乾报表优化与性能管理.docx_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

润乾报表优化与性能管理编制者:吴国邦目录第一章、报表优化41. 灵活应用多数据集41.1.1.网格式、分组式、交叉式尽量用单数据集41.1.2.多源分片、主子报表尽量用多数据集52. 写sql的技巧72.1.1.尽量在sql里进行group72.1.2.尽量不用select * from82.1.3.尽量在sql里排序82.1.4.尽量在sql里过滤82.1.5.大数据量可以采用存储过程83. 当前行、当前组的概念93.1.1.select函数93.1.2.select1()函数103.1.3.group函数104写表达式的技巧124.1.or/| 操作符124.2.and/& 操作符124.3.过滤条件124.4.二分法查找函数bselect1134.5.巧用空值判断nvl144.6.数据类型的考虑155. 枚举分组165.1.enumgroup函数165.2.plot函数176. 如何减少冗余单元格占用内存196.1.空白单元格的应用196.2.慎用隐藏行列196.3.慎用合并单元格19第二章、性能管理217.单用户缓存217.1.1.概念定义217.1.2.功能背景217.1.3.使用方法217.2.多用户间共享缓存227.2.1.概念定义227.2.2.功能背景227.2.3.控制方式237.2.4.使用方法237.3.静态并发控制257.3.1.概念定义257.3.2.功能背景257.3.3.使用方法257.4动态并发控制267.4.1.概念定义267.4.2.功能背景267.4.3.使用方法267.5.大报表运算中断277.5.1.概念定义277.5.2.功能背景277.5.3.使用方法277.6.集群时缓存同步287.6.1.概念定义287.6.2.功能背景287.6.3.使用方法298.7. 表达式预解析308.7.1.概念定义308.7.2.功能背景308.7.3.使用方法30第一章、 报表优化1. 灵活应用多数据集1.1.1.网格式、分组式、交叉式尽量用单数据集看如下的报表:图1.1.这是一个比较典型的多层交叉报表,其做法有两种:第一种:图1.2.这种做法设计了五个数据集,每一层的表头都来自一个码表,交叉点的数据汇总时根据条件和表头关联第二种:图1.3.这种做法只设计了一个数据集,把码表和事实记录表叉乘起来,在报表中进行分组扩展 我们试比较一下两种做法的优缺点:第一种做法:1. 数据集不需要对多表进行叉乘,取数速度快2. 事实记录数据集可以在sql里先进行分组聚集操作,减少取过来的记录书,加快取数的速度和报表运算速度3. 表头扩展直接对码表进行select操作,运算速度快4. 交叉点汇总需要对事实记录表进行检索遍历,查找出和表头关联的记录进行汇总,交叉点的格子数远远大于表头单元格的个数,事实记录表的记录数也一般远远大于码表的记录数,每个交叉点都要对事实记录表遍历检索一次,运算速度非常慢第二种做法:1. 数据集需要对码表和事实记录表进行叉乘,取数速度慢,但是一般情况下码表的字段数只有一两个,而且数据库有索引,记录数不是非常大的情况下慢不了很多2. 在数据集sql里就可以对表头字段先进行分组聚集,这样取过来的记录数大大减少,加快了取数速度和报表的运算速度3. 表头单元格是对事实记录表进行分组操作,然后再扩展,比第一种做法慢一些,但是由于对数据集只要进行一次的分组操作,因此慢不了太多4. 交叉点汇总不需要再对事实记录表进行检索遍历了,而是直接对当前组集里的记录进行汇总,因此速度大大提高了总结:第二种的做法性能优于第一种1.1.2.多源分片、主子报表尽量用多数据集看如下报表:图1.4.这是一个比较典型的主子报表,主表一条记录对应子表多条记录,是个典型的一对多的关系,再引伸一下,一个主表可以对应多个子表,每个子表都是多条记录。 此时做法还是存在两种:第一种:1. 每个主表和子表分别定义一个数据集,在报表里通过条件把子表和主表关联起来2. 优点:避免了表间叉乘,减少了数据量,加快了取数速度和数据库的运算速度。3. 原因:对于主子报表,主表的字段数一般比较多,而子表一般有多条记录和主表的一条记录关联,同时子表间往往没有关联关系,因此如果叉乘会导致数据量大大增加,在多子表的情况下这个现象尤其明显4. 缺点:子表取数扩展时,需要根据条件和主表记录关联,需要对子表记录进行遍历检索,但是大部分的情况下,主表只有一条记录或者只有十几条记录,因此对子表的遍历检索次数不会很多第二种:1. 只定义一个数据集,把主表和所有子表叉乘起来2. 缺点:由于子表之间没有关联关系,且主表的字段数比较多,叉乘往往导致记录数呈几何级数增加3. 优点:子表取数扩展时,不需要对子表记录进行遍历扩展,运算速度快点总结:第一种做法的性能优于第二种2. 写sql的技巧2.1.1.尽量在sql里进行group对于汇总类型的报表,往往需要进行分组聚集运算,如果在数据库中先进行一次分组聚集,能够大大减少取到报表服务器的记录数,加快取数和报表运算的速度。看如下报表:图1.5.这是一个典型的交叉分组报表,其sql有两种写法:第一种:select 产品,客户,销量 from 购买记录表第二种:select产品,客户,sum(销量) from 购买记录表 group by 产品,客户而报表的做法都一样,如下图所示:图1.6.分析:采用第一种做法,不仅仅取到报表服务器上记录数多了,取数速度慢,而且在报表端对购买记录表进行分组运算的时候速度也慢了;采用第二种做法,数据库虽然要进行分组运算,但是数据库中有索引,运算速度快,且取到报表服务器端的记录数大大减少,取数速度大大加快,因此在报表端进行分组运算的时候只要对很少的记录数进行,报表的运算速度大大加快了总结:第二种做法的性能远远优于第一种2.1.2.尽量不用select * from对于初学者来说,这是一个很容易犯的错误,例如报表中只需要用到三个字段,但是数据库中实际的表有十个字段,一些初学者习惯性的用select * from table1,这样相当于把十个字段的数据都取到报表服务器端,增加了报表服务器端的内存占用以及减慢了运算速度正确的写法是:select col1,col2,col3 from table1,即用到哪几个字段就取哪几个,用不着的不要取2.1.3.尽量在sql里排序报表中往往需要对数据进行排序,排序运算可以在数据库中进行,也可以在报表端进行,如果报表中的排序规则是确定的,那么建议排序操作选择在数据库端进行,因为数据库中有索引,且数据库是c语言开发的,数据运算速度快。2.1.4.尽量在sql里过滤这个问题和2.1、2.2是类似的,报表很多时候并不需要对表中的所有记录进行操作,而是对部分满足条件的记录进行操作,因此建议过滤操作在数据库中进行,这样取到报表服务器端的记录数大大减少,既加快了取数的速度,也加快了报表的运算速度,因为报表需要处理的数据少了。2.1.5.大数据量可以采用存储过程有时候,需要用于汇总统计的原始数据量非常大,如果每次生成报表都需要现算,一方面非常慢,另一方面数据库的压力会很大,此时可以采用存储过程对数据预先进行一次压缩,生成中间表,然后再基于中间表生成报表,可以大大提高运算速度并减轻数据库的压力。3. 当前行、当前组的概念3.1.1.select函数使用select函数时,相当于从数据集中取出一组符合条件的记录集合,在单元格中进行扩展,此时每个扩展出来的单元格都保留一个指针,指向当前记录,即当前行,因此在这些单元格的附属单元格中,应当直接用“数据集名.列名”来引用同一个数据集同一条记录的值,此时报表引擎不需要对数据集进行检索遍历了,而是直接从当前行中取值。图示:图1.7.典型的select用法:图1.8.不合理的用法:图1.9.3.1.2.select1()函数select1的函数和select函数的区别在于,它每次只取出一条记录,但是当前行的概念是一样的,当它从数据集中取出一条记录时,保留了一个指针指向该记录,因此他的附属单元格里只需要利用“数据集名.列名”即可从该记录中取值,而不需要重新检索遍历数据集。正确的select1的用法:图1.10.它和select函数还有一个区别在于:当它检索数据集时,检索到第一条满足条件的记录随即把该记录返回,而不继续往下检索;对于select来说,即使已经检索到满足条件的记录了,还会继续往下检索,直到所有记录检索完为止,因为select的任务是检索出一组记录,它还不确定后面是否还有满足条件的记录。因此,如果你确定只要从数据集中取出一条记录,那么请一定用select1而不要用select3.1.3.group函数group函数是对数据集按照某个字段或者表达式进行分组,获得一组组的集合,然后从每组中取出一个指定字段或者表达式的值,放到单元格中进行扩展,扩展出来的每个单元格都保留了一个指针指向当前的组集,该组集称为当前组。因此在附属单元格中,需要对该组集进行操作时,不需要用任何条件和主单元格关联了,如果加设了条件,反倒画蛇添足,导致报表引擎还对组集中的记录进行遍历检?鳌?正确的group 用法:图1.11.不合理的group用法:图1.12.group函数的原理图示:图1.13.4写表达式的技巧4.1.or/| 操作符使用or操作符时,尽量把值为true的可能性更大的条件表达式放在or的前面,为true可能性更小的条件表达式放在or的后面原因:or操作符的左右两个操作数,只要有一个为true,其结果必定为true,因此只要第一个条件表达式算出来是true,后面的条件表达式就没必要算了,这样可以加快运算速度。其次,虽然润乾报表提供了or和|两种写法,这么做仅仅为了方便习惯写or的用户,事实上表达式中写|可以加快表达式的解析速度。因此建议:尽量写| ,少写or4.2.and/& 操作符使用and操作符时,尽量把值为false的可能性更大的条件表达式放在and的前面,为false可能性更小的条件表达式放在and的后面原因:and操作符的左右两个操作数,只要有一个为false,其结果必定为false,因此只要第一个条件表达式算出来是false,后面的条件表达式就没必要算了,这样可以加快运算速度。其次,虽然润乾报表提供了and和&两种写法,这么做仅仅为了方便习惯写and的用户,事实上表达式中写&可以加快表达式的解析速度。因此建议:尽量写& ,少写and4.3.过滤条件润乾的内置数据集函数中,有不少函数带有过滤条件参数,例如count(), sum(), avg, max(), min() 等等,很多时候可能用户需要把数据集当前记录行集全部选出,而不需要过滤,此时不少用户习惯直接把过滤条件写成true,殊不知,这样导致报表引擎运算时仍旧需要对每条记录进行判断,而如果直接省略该参数,那么引擎就会直接跳过判断,直接进行运算,速度快很多。图1.14.4.4.二分法查找函数bselect1本文1.3.2中提到了,select1函数是从数据集中检索出满足条件的第一条记录,然后返回该条记录的选出表达式的值,而且还有当前行的概念,可以保证其附属格中以最快的速度从同一条记录中获取相应字段的值。Select1函数的检索方法是从第一条记录往下遍历,这种检索算法在记录按照检索条件已经排好序的情况下,比二分法慢,因此润乾报表还提供了二分法检索的函数。bselect1就是采用二分法检索的函数。二分法检索算法介绍:例如存在A-Z按照检索条件排好序的23个数据,二分算法首先找到最中间的那个数M,比较M和检索条件是否相等,如果相等,直接返回M,运算结束;如果不等,那么是大了还是小了,假设大了,那么指针直接指向A和M中间的那个?鼼,再判断是否相等,如果相等,直接返回G,运算结束;如果不等,就看大了还是小了,假设G小了,那么指针直接指向G和M中间的那个数,继续进行判断,以此类推。数据集函数:bselect1()函数说明: 此函数功能等同select1(),但是算法不同,采用二分法,适用于数据集记录已经按照参考字段排好序的情况,运算速度比select1()快语法: datasetName.bselect1(selectExp,referExp1,referDescExp1,referValueExp1)参数说明: selectExp 选出字段或表达式referExp1 参考字段表达式referDescExp1 参考字段表达式的数据顺序,true表示降序排列,false表示升序排列referValueExp1 参考字段的值表达式,一旦找到参考字段和该值相同的记录,即返回selectExp的值.参考字段及其值可以多个,如果是多个,则找到多个参考字段都和值匹配的记录才返回rootGroupExp 是否root数据集表达式返回值: 数据类型不定,由selectExp的运算结果决定示例:例1:ds1.bselect1(name,id,false,value() 采用二分法,找到数据集ds1中id和当前格的值相等的记录,返回其name字段值例2:ds1.bselect1(name,id,false,value();class,false,A1;sex,true,B1)采用二分法,找到数据集ds1中id和当前格的值相等、class和A1相等且sex和B1相等的记录,返回其name字段值。注意这三个条件在表达式中的顺序必需和它们在数据集中的排序先后相同,也就是说,在数据集中是先对id升序排序,再对class升序排序,最后对sex进行降序排序的。4.5.巧用空值判断nvl表达式中,经常需要用到空值判断,例如在单元格的显示值属性中,判断当单元格的值为空时,显示为0,否则显示单元格的真实值,等等。一般这种情况下,用户习惯写的表达式是: if(value()=null, 0, value()。如果我们把value()换成更加复杂的表达式,例如if(ds1.select1()=null, 0, ds1.select1(),大家可以看出,这种算法明显很慢,需要把ds1.select1()这样的复杂表达式运算两次,而如果采用nvl()则可以避免这个问题。单元格函数:nvl()函数说明: 根据第一个表达式的值是否为空,若为空则返回指定值语法: nvl( valueExp1, valueExp2 )参数说明:valueExp1 需要计算的表达式,其结果不为空时返回其值valueExp2 需要计算的表达式,当valueExp1结果为空时返回此值返回值: valueExp1或valueExp2的结果值示例:例1:nvl(A1,) 表示当A1为空时,返回空串,否则返回A1例2:nvl(value(),0) 表示当当前格为空时返回0,否则返回当前格的值应用举例:图1.15.4.6.数据类型的考虑数值型的数据,根据其精度不同,可以分成好几种,例如:整型数据有short(16位),int(32位),long(64位),BigInteger(大于64位);浮点型数据有float(32位), double(64位),BigDecimal(大于64位)。一般来说,精度越高的数据类型,运算速度越慢,因此,如果您的数据长度没有那么长,那么建议选择精度相对比较低的数据类型,可以加快运算速度。快逸报表提供的数值型转换函数有:float() 转换成32位的浮点数double() 转换成64位的浮点数decimal() 转换成大于64位的浮点数integer() 转换成32位的整数 long() 转换成64位的整数bigint() 转换成大于64位的整数number() 转换成相应的32位整数、64位整数、或者64位符点数请用户在选择以上函数时根据数据的长度慎重选择。5. 枚举分组5.1.enumgroup函数请看如下报表:图1.16.这是一个不规则分组的报表,将饮料和点心归入副食品组,肉/家禽和海鲜归入肉类组,日用品归入日用品组,其他所有类别归入其他组。设计这样的一个报表有多种做法,下面我们列出比较典型的两种:第一种做法:图1.17.第二种做法:图1.18.分析:第一种做法是比较常规的做法,首先在第一列中根据分组要求,枚举出三个组,然后分别在第二列、第三列、第四列里对数据进行汇总时,根据分组条件增加过滤条件,如类别ID=1 or 类别ID=3等等,一般的传统报表工具都是这种做法。这种做法的弊端在于:引擎对每一个汇总项进行计算时,都需要对数据进行一次遍历,查找出满足条件的记录进行汇总,因此计算速度很慢。第二种做法采用了enumgroup函数,这种做法是对按照枚举分组规则数据集先进行分组,之后在第二列、第三列、第四列里对数据进行汇总时直接从当前组里取数,不再需要遍历和过滤了。因此第二种做法速度非常快,性能比较优。5.2.plot函数请看如下的报表:图1.19.这是一个典型的按照时间段来分组的报表,它有如下两种做法: 第一种:图1.20.第二种:图1.21.分析:第一种做法采用plot函数,plot函数的功能是对数据集按照给定的数据段进行按段分组,有几个数据段就分成几个组,之后按照数据段的个数对单?因此,第一种做法的优点是:采用按段分组函数,只需要对数据集进行一次分组,附属格对组集进行汇总运算时不需要对记录进行遍历检索了,大大加快了运算速度第二种做法,是比较常规的做法,目前传统报表工具基本上只能采用这一种做法,他把数据段挨个列出来,附属单元格中逐个编辑表达式,通过过滤条件和数据段关联,这种做法每次运算都要检索遍历数据集,运算速度非常慢。总结:第一种做法的性能远远优于第二种6. 如何减少冗余单元格占用内存6.1.空白单元格的应用请看如下报表:图1.22.这个报表中,粉红色背景的单元格都属于没用的单元格,但是很多时候必须留着占位用。例如:c2单元格,其目的是把报表日期和报表编号分隔开,省得连在一起难看,同时当b4横向扩展出很多单元格时,报表日期要靠右对齐,因此中间必须有c2来占位。由于润乾报表的界面模型是个规整的矩形,不可能在中间或者边上挖去一块,因此你会发现报表中时常会多出一些无谓的占位格。在内存中,一个单元格就要占用一块内存,因此单元格越少越好,这种情况下可以尽量使用空白单元格。空白单元格在内存中是个null,基本不占用内存,因此对于报表边上、中间一些占位格,尽量设成空白单元格,这样既达到了占位的效果,又不会占用内存。6.2.慎用隐藏行列报表中为了进行一些复杂的运算,往往需要用到隐藏行列来处理中间的运算,而这些隐藏行列中被用到的单元格往往只有一两个格子,整行整列的单元格的个数往往很多,此时没被用到的单元格会额外浪费内存,因此要记住把没用的单元格设为空白单元格6.3.慎用合并单元格合并单元格的所有属性都存在左上角的格子中,而合并区域中的其他被合并格并不保存任何属性也不占用内存,因此,做报表的过程中,不少用户习惯对于没用的单元格合并起来,减少内存的占用。殊不知,这种做法虽然减少了内存,但是由于合并格的运算牵扯到主合并格和被合并格的关系,运算比较复杂,会降低运算速度,因此,我们建议:没用的格子设为空白单元格,尽量不要合并。举例:图1.23.第二章、性能管理7.单用户缓存7.1.1.概念定义单用户缓存是指当某个客户端访问某个报表,引擎将其计算出来后,会将运算结果缓存下来。同一个客户端访问完该报表后,如果需要对同一报表结果进行别的操作,例如打印、导出、翻页等,引擎直接从缓存里取报表结果,而不必重新计算。7.1.2.功能背景由于WEB服务器与浏览器之间无连接的特性,导致B/S方式下服务器端实体(在我们报表系统中主要是指报表模板、报表及报表分页)的生命周期无法完全与浏览器端保持一致。举例来说,客户端访问了一张报表,报表计算且向客户端输出完毕后,是否应当从内存中清除报表对象呢?服务器无法判断客户端是否还需要使用这个对象,事实上,客户端往往还需要翻页、打印、导出等操作,此时还需要使用报表对象;而客户端也完全有可能关闭浏览器,不再访问了。因此,如果服务器端清除了报表对象,则客户端进行翻页、打印、导出等操作时,不得不重新进行计算,浪费cpu;如果客户端不再访问了而服务器端却保留着报表对象,则会浪费内存。为了解决这个问题,我们对这些实体采取了带时间管理的缓存策略如果通过tag标签访问,自动会缓存报表。通过调用API接口计算报表,如果不调用缓存管理器的API,就不会进行报表缓存。7.1.3.使用方法缓存时间和缓存目录的配置在reportConfig.xml中,其中时间以分钟为单位,如下所示: cachedReportDir c:runqiancached cachedReportTimeout 120 cachedParamsTimeout 120说明:1. 如果缓存报表超过最大未访问时长而没有被访问,则会被引擎清除。2. 引擎对用户输入的参数也做了缓存,这个缓存是在内存中的。当报表缓存被清除时,如果用户请求翻页等操作,引擎会利用参数缓存自动重新计算报表,而不需要用户重新输入参数3. 如果用户请求翻页等操作时,参数缓存也被清除了,就会提示用户重新访问并输入参数4. 一般来说,参数的最大未访问时长应当比报表的最大未访问时长更长,否则没有意义。5. 引擎每隔5分钟扫描一次缓存,清除超时缓存。因此,如果上一次扫描刚结束时才到达缓存期限的报表,得到下一次扫描时才会被清除,等于延长了4.999.分钟,这里的9理论上可以无穷多,接近5分钟。举例来说,缓存期限为2分钟的报表,如果在扫描结束后才到2分钟,那么下一次扫描时相当于已经缓存了6.999.分钟;再举例,缓存期限为6分钟的报表,如果在扫描结束时才到6分钟,那么下一次扫描时可能已经缓存了10.999.分钟了。7.2.多用户间共享缓存7.2.1.概念定义当用户A访问报表A时,引擎会把计算结果缓存下来,当用户B(也可能是用户A再次访问)以同一参数再次访问时,引擎直接把缓存报表返回,而不必重新计算。7.2.2.功能背景用户间共享缓存的目的,是为了避免不同用户访问同一张报表时重复运算的问题。因此可以把A用户访问报表时计算出的结果报表保存下来,当B用户也访问这个报表时,直接把保存下来的结果报表返回给B用户,不再重新计算。对于带有参数和宏的报表,当用户采用相同的参数和宏进行重复访问时,也可以利用缓存,减少重复的计算。但是如果参数和宏不一样,报表就只能重新计算,因为不同参数运算出来的结果报表不一样,无法利用缓存。因此,对于有参数和宏的报表,缓存时还必须识别参数和宏的值。7.2.3.控制方式用户间共享缓存包括三个层面,模板共享、结果报表共享、分页后报表共享,我们可以通过三种方式对其进行控制。 授权控制授权控制主要是用来控制结果报表共享和分页后报表共享的。一般是由用户所获得的授权来决定。 参数控制参数控制主要是用来控制模板共享的。若要实现多用户之间共享模板,可以通过配置reportConfig.xml文件中alwaysReloadDefine参数来实现。设置alwaysReloadDefine的value为yes时,模板不可以被共享;设置alwaysReloadDefine的value为no时,可以实现模板之间的共享。 标签控制标签控制主要是用来控制结果报表共享和分页后报表共享的。一般是通过tag标签中的useCache与timeout属性来设置的。当且仅当reportConfig.xml里的alwayReloadDefine属性设置为no时,tag标签中的useCache与timeout属性才会起作用,useCache属性控制是否启用缓存,而timeout为取多少长时间内生成的报表.7.2.4.使用方法 参数控制相关配置在reportConfig.xml中,其中时间以分钟为单位,可配置的属性如下所示: alwaysReloadDefine no cachedReportDir c:runqiancached cachedReportTimeout120 cachedParamsTimeout 120 说明:1. alwaysReloadDefine这个参数如果被关闭(即设置为yes),那么每次新任务请求都直接装载模板重新计算报表,不会读取缓存2. 在1的情况下,新读取的模板和新计算的报表照样会被缓存,其目的是为了实现3.1中的功能3. 因此在1的情况下,意味着缓存中的对象会无限庞大,直到缓存对象过期才会被清除。所以,如果不是特殊需要,一般建议不要关闭alwaysReloadDefine。4. 如果必须关闭alwaysReloadDefine,那么建议缓存时间设置短一点,例如半小时,一般用户浏览一个报表半小时内还不翻页打印导出的话,多半也不会再次操作了。这样可以让缓存对象清除得及时点,避免缓存过于庞大。 首先先将reportConfig.xml里的alwayReloadDefine属性设置为no时,然后在发布报表的页面中TAG中使用useCache和 timeout属性。 上述属性的设置表示在如果A用户读取了报表wangge.raq,那么在30分钟内,如果B用户去读取wangge.raq报表时,系统不再计算该报表,只是从缓存中读取该报表,并返回给B用户,同时将缓存中wangge.raq的缓存时间修改为B用户读取的时间。 7.3.静态并发控制7.3.1.概念定义静态并发控制就是在服务器端预先配置允许并发的最大任务数,当请求任务超出了这个数,就被迫进行等待,直到有算完的任务退出,等待的任务才能进来计算。7.3.2.功能背景多任务并发时,通过控制任务数避免过多的任务数同时运行造成的内存溢出7.3.3.使用方法在润乾web应用根目录下的WEB-INF/reportConfig.xml文件中进行配置,可配置的属性包括: maxConcurrentForReport 9 maxWaitForReport 99 maxWaitTimeForReport 30说明:1. 当等待任务数超过最大等待数时,新请求的任务会直接返回错误信息;2. 当某个任务造成内存溢出时,为了让并发的其他任务能顺利运行,必须经过一定的等待时间,才允许新任务访问,这个时间由maxWaitTimeForReport决定7.4动态并发控制7.4.1.概念定义由用户根据服务器硬件的配置,预先设置一个允许并发运算的最大格子数,然后由服务器运算的过程中,动态的智能判断当前并发访问的格子数是否达到预设值,如果已经达到预设值,则阻止新任务访问,提示:报表格子数超标,稍候再访问。7.4.2.功能背景由于静态并发数是一个无法精确控制的数据,因此引入最大单元格数。这个数据是根据服务器内存能支撑最大的格子数来设定的。通过它,可以灵活地改变并发数控制,如果报表都很小,则允许更多的并发数,如果报表都很大,则只允许很少的并发数。7.4.3.使用方法在润乾web应用根目录下的WEB-INF/reportConfig.xml文件中进行配置,可配置的属性为:maxCellNum:动态并发配置的主要指标,用来表示在同一时刻,所能计算的最大的单元格数量。服务器在运算过程中,动态的智能判断当前并发访问的格子数是否达到预设值,如果已经达到预设值,则阻止新任务访问,提示:报表格子数超标,稍候再访问。同时,为了让报表引擎在计算报表之前就能够智能地判断报表的格子数,报表属性里还提供了报表格数属性,如下图所示:图2.1.报表引擎在计算完数据集,计算报表之前,都会先读取报表格数属性,计算出该报表可能的格子数,然后叠加到内存中的一个当前格数变量中,然后利用这个变量和reportConfig.xml文件中的maxCellNum进行对比,如果当前格数超过了maxCellNum,就不允许这个报表计算,如果没有超过,就进行计算。从而达到了动态控制并发数的目的。7.5.大报表运算中断7.5.1.概念定义在服务运行期间,对运算时间较长的大报表进行中断操作,释放cpu和内存来计算其他报表。7.5.2.功能背景当某个大报表运算很长时间时,为了让别的任务能够正确进行计算,不会等待太长时间,允许对该大报表执行中断,使之空出cpu和内存。7.5.3.使用方法通过调用API获得正在计算的报表entry,并且调用API中止报表的运算。代码示例:CacheManager.getInstance().getReportEntry(String reportName). getReportCache(Context ctx, long timeout). interrupt()/中断单个报表,这里的timeout是自己设的,你希望删除多长时间内计算的报表 CacheManager.getInstance().getReportEntry(String reportName). getReportCache(String reportCacheId). interrupt()/中断单个报表 CacheManager.getInstance().getReportEntry(String reportName). getReportEntries();/获得该报表正在计算的所有实例,然后循环调用interrupt()方法逐个删除 CacheManager.getInstance().getReportEntries().keySet() /列出报表名称说明:1. 中断单个报表的运算时,报表模板名为tag标签中的reportFileName或者beanName2. alwaysReloadDefine设为no时,才可以正确中断3. 对于比较大的报表,临界内存的情况下,中断请求发出后,需要等待一会,才能中断成功7.6.集群时缓存同步7.6.1.概念定义客户端在多次访问集群服务器的不同主机时,服务器之间可以进行报表缓存的同步,使得客户端能够返回正确的结果而不需要重新计算。7.6.2.功能

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论