当报表出现性能问题,需要对数据源计算进行优化时,控制执行路径是一种有效的方法,但也是阻碍优化的难题。这是由于数据库执行路径不透明,程序员很难甚至无法干预执行路径,进而也就难以提高数据库访问的性能。而对于一般报表工具来说,由于不具备强计算能力,大部分计算仍然要依靠数据库进行,也就导致很多报表优化的效果不甚理想。

不同于一般报表工具,润乾报表在这一点上,由于内置了专门用于数据计算的集算引擎。与数据库执行 SQL 路径不可控相比,集算脚本的执行过程是可控的,开发人员可以通过编写集算脚本完成报表数据源准备,并根据实际情况调整计算执行过程,从而完成报表优化工作。

集算引擎内置了丰富的结构化数据计算的类库,例如连接操作,就包括普通连接 join()、按序号对应连接 pjoin()、叉乘连接 xjoin()等,而针对维表和事实表则提供了更加高效的连接方式 switch(),这样就为开发人员在优化报表时提供了多种选择。此外,由于集算报表支持分步编写,开发人员可以自由决定计算顺序,先算什么后算什么,对一个复杂计算进行合理拆分和整合,复用中间结果,从而通过改变计算顺序来进行优化。

下面是一个针对报表 SQL 数据源优化的实例过程和效果,用户在使用润乾报表(结合集算器实现)时可以参考。

该报表是一张明细表,数据量较大,涉及到的数据库表有几十个之多,数据库表间关联频繁(包括自连接的情况),同时报表中包含多个格间计算表达式(比值和汇总值)。

其中较复杂的数据集 SQL(近 400 行)如下所示:

select t.*from (select *from (select syb.org_abbreviation as syb,max(xmb.org_abbreviation) as xmb,--省略多个连接、判断、汇总语句left join losrrr losr on losr.requisition_id =l.requisition_idwhere l.table_type = '1'and l.requisition_state = '0100500005000000006'and nvl(l.bsflag, 0) != 1group by l.requisition_id,l.note,--省略多个分组字段losr.standby_param3,losr.standby_param6) aLEFT JOIN crview ve  --视图ON ve.requisition\_id = a.req\_id

select t.*   from (select *           from (select syb.org_abbreviation as syb,                        max(xmb.org_abbreviation) as xmb,                   --省略多个连接、判断、汇总语句                   left join losrrr losr on losr.requisition_id =                   l.requisition_id                  where l.table_type = '1'                    and l.requisition_state = '0100500005000000006'                    and nvl(l.bsflag, 0) != 1                  group by l.requisition_id,                           l.note,                           --省略多个分组字段                           losr.standby_param3,                           losr.standby_param6                 ) a           LEFT JOIN crview ve  --视图             ON ve.requisition\_id = a.req\_id

仔细看这个 sql 会发现,首先关联的表比较多,包括很多自关联的情况,其次嵌套了很多子查询,最后又与一个视图进行关联(而视图本身的复杂程度也与上述 SQL 类似)。

实际使用中,该报表查询 4 个月数据所需展现时间为 6 分 42 秒,远远达不到用户要求。显然由于 SQL 比较复杂,数据库执行路径难以控制,所以很难在 SQL 的层面再进行优化。

在使用了润乾报表后,进行优化的过程如下:

1、编写集算脚本

1)拆分原报表数据集 SQL。这个 SQL 慢的原因在于两个子查询之间的 join,那么分别把两个子查询 sql 写到集算脚本中执行,并且在集算脚本中使用 switch 完成关联。

2)消除报表格间运算。将原报表模板中的格间计算(比值和汇总值)的内容全部移到集算脚本中完成,由此减少格子遍历的过程,可以提升性能。

3)将结果集一次返回给报表。在使用集算脚本完成了所有数据准备的工作后,将结果一次性返回给报表工具,报表接收到数据后直接进行展现,不再做类似格间计算这样影响效率的计算。

完整的集算脚本如下:

  A B C D E F
1 =connect("xcoms2")          
2 =A1.query(${sql1}) /sql 通过宏传递        
3 =A1.query(${sql2})          
4 =A2.switch(REQ_ID,A3:REQUISITION_ID)        
5 =A4.new(#:SN,SYB,  XMB,  SUB_ID,  ORG_ABB,  REC_NOTICE_ORG_ID,  XZ_TEAM,  XZ_ORG,  REQ_CD,  REQ_ID,  REQ_NOTE,  SFLJ,  SFYY, SFZL,  OPS_RECORD_ID,  REQ_TYPE,  TASK_GOAL,  WELL_NAME,  WELL_SORT,  WELL_TYPE,  BLOCK,  PRO_NAME,  SGGY,  YQZH,  OIL_REGION_CODE,  YQXL,  SRM,  BEGIN_TIME,  BACK_TIME,  DOWN_TIME,  SETUP_TIME,  IS_FAIL,  FINISH_STATUS,  WCZT,  JFDW,  REQ_ZYXM,  DESIGN_WELL_DEPTH,  NOTE1,  YJ,  SJ,  LEADER,  XJZCS,  CGCS,  HJYS,  YQYZ,  PLAN_CORE_NUM,  GET_CORE_NUM,  FIRE_NUM,  SEND_NUM,  GET_NUM,  ELIGIBILITY_NUM,  ZYRY,  USE_BULLET_NUM,   SEND_BULLET_NUM,  ZSKM,  SKM,  JCH,  QBQX,  YDQX,  HGQX,  SKD,  KM,  ZYSJ,  ZZYSJ,  GZSJ,  GGXH,  QSLB, REQ_ID.REQUISITION_ID:REQUISITION_ID,  REQ_ID.REQUISITION_TYPE:REQUISITION_TYPE,  REQ_ID.BACK_DATE:BACK_DATE,  REQ_ID.REPORT_BASE_TIME:REPORT_BASE_TIME,  REQ_ID.RWD_SUB_ID:RWD_SUB_ID,  REQ_ID.JTZ_SUB_ID:JTZ_SUB_ID,  REQ_ID.GUN:GUN,  REQ_ID.BUM:BUM,  REQ_ID.RECEIVE_DATE:RECEIVE_DATE,  REQ_ID.JJTJ:JJTJ,  REQ_ID.ASSESS_DATE:ASSESS_DATE,  REQ_ID.PDTJ:PDTJ,  REQ_ID.ZYXM:ZYXM,  REQ_ID.CLM:CLM,  REQ_ID.JDF:JDF,  REQ_ID.JDT:JDT,  REQ_ID.SDM:SDM,  REQ_ID.JJM:JJM,  REQ_ID.JSM:JSM,  REQ_ID.JD:JD,  REQ_ID.JFDW1:JFDW1,  REQ_ID.JFDW2:JFDW2,  REQ_ID.JFDW3:JFDW3,  REQ_ID.SBCS:SBCS,  REQ_ID.FHCS:FHCS,  REQ_ID.SYQCS:SYQCS ,if(CGCS==null || CGCS==0 || XJZCS==null || XJZCS==0,0,CGCS/XJZCS*100):PERCENT1,  if(CGCS==null || CGCS==0 || (XJZCS-HJYS)==null || (XJZCS-HJYS)==0,0,CGCS/(XJZCS-HJYS)*100):PERCENT2,  if(HGQX==null || HGQX==0 || QBQX==null || QBQX==0,0,HGQX/QBQX*100):PERCENT3,  if(FHCS==null || FHCS==0 || SYQCS==null || SYQCS==0,0,FHCS/SYQCS*100):PERCENT4,  if(FHCS==null || FHCS==0 || SYQCS==null || SYQCS==0,0,FHCS/SYQCS*100):PERCENT5 )
6 // 以下 A7-F12 求汇总值          
7 =A5.sum(YJ) =A5.sum(SJ) =A5.sum(XJZCS) =A5.sum(CGCS) =A5.sum(HJYS) =A5.sum(YQYZ)
8 =if(D7==0 || D7==null || C7==0 || C7==null,0,D7/C7*100) =if(D7==0 || D7==null || C7-E7==0 || C7-E7==null,0,D7/(C7-E7)*100) =A5.sum(JDF) =A5.sum(JDT) =A5.sum(CLM) =A5.sum(SDM)
9 =A5.sum(JJM) =A5.sum(JSM) =A5.sum(PLAN_CORE_NUM) =A5.sum(GET_CORE_NUM) =A5.sum(FIRE_NUM) =A5.sum(SEND_NUM)
10 =A5.sum(GET_NUM) =A5.sum(ELIGIBILITY_NUM) =A5.sum(ZSKM) =A5.sum(SKM) =A5.sum(JCH) =A5.sum(SRM)
11 =A5.sum(QBQX) =A5.sum(HGQX) =A5.sum(YDQX) =if(B11==0 || B11==null || A11==0 || A11==null,0,B11/A11*100) =if(C11==0 || C11==null || A11==0 || A11==null,0,C11/A11*100) =A5.sum(SBCS)
12 =A5.sum(SYQCS) =A5.sum(FHCS) =if(B12==0 || B12==null || A12==0 || A12==null,0,B12/A12*100) =A5.sum(ZZYSJ) =A5.sum(ZYSJ) =A5.sum(GZSJ)
13 >A5.insert(0,"合计","","","","","","","","","","","","","","","","","","","","","","","","","", F10,"","","","","","","","","","","", A7, B7,"", C7, D7, E7, F7, C9, D9, E9, F9, A10, B10,"","","", C10, D10, E10, A11, C11, B11,"","", E12,"", F12,"","","","","","","","","","","","","","","", E8, C8, D8, F8, A9, B9,"","","","", F11, B12, A12, A8, B8, D11, E11, C12)
14 return A5          

2、设计报表

在润乾报表中调用上述集算脚本,编辑报表表达式完成报表制作。

优化效果

报表展现要经历两个阶段:1 数据源计算(执行数据集 SQL)阶段,2 报表计算并展现阶段。两个阶段的时间以及总的时间在优化前后的对比如下:

  数据集计算 报表计算展现 总时间
优化前 317S 85S 402S
优化后 52S 5S 57S

通过上面的过程,该报表展现时间从原来的 6 分 42 秒,锐降到了 57 秒,不到 1 分钟的时间,达到了用户预期的目标。

针对不同的场景,润乾报表都有相应的优化方案,上述计算过程的优化适用于数据库取出数据量不是很大的场景(Oracle JDBC 速度非常慢)。如果数据量很大,还可以使用润乾报表的大数据集功能,请参考相关文档。

更多性能优化相关问题请查看:性能优化相关问题分类导航

润乾报表实现计算过程性能优化相关推荐

  1. 润乾报表实现无数据源的规则报表及改进

    某报表系统中有部分报表需要按照一定规则显示数据,如:显示查询日期范围内的奇数日数据,要求数据库中即使无记录该日期也显示(内容为空). 本文重点来实现奇数日期序列,数据区不是重点,故置空. 以上述报表需 ...

  2. 润乾报表分组求和_实现报表数据预先计算

    报表应用中,如果数据量较大或计算过程较复杂,往往会导致报表数据源准备过慢,从而影响报表性能.这种情况下可以预先计算报表需要的数据,在呈现时直接引用,使得用户在访问报表时可以迅速地获得响应. 一.当前的 ...

  3. 润乾报表CookBook与使用

    part1 1. 数据源相关 1.1 报表工具连接文本数据 1.2 报表工具连接非关系数据库(待补充) 1.3 报表异构数据源关联混算 1.4 报表工具 json 数据源 1.5 报表工具连 sap ...

  4. 润乾报表实现组内排序报表及改进

    报表开发中经常会遇到需要进行组内排序的报表,如按月份的分组汇总值排序显示,并显示每月销售额前十名的记录.使用报表工具一般通过隐藏行列辅助可以实现,下面通过实例说明润乾报表的实现过程,以及改进方案. 报 ...

  5. 润乾报表html图片自适应,润乾报表

    润乾报表是一个纯JAVA的企业级报表工具,支持对J2EE系统的嵌入式部署,无缝集成.服务器端支持各种常见的操作系统,支持各种常见的关系数据库和各类J2 EE的应用服务器,客户端采用标准纯html方式展 ...

  6. birt 报表与润乾报表对比

    BIRT,全称Business Intelligence and Reporting Tools,是为 Web 应用程序开发的基于 Eclipse 的开源报表系统,它的特点在于以 Java 和 Jav ...

  7. 右边补0 润乾报表_制作按奖金分段统计的员工业绩报表

    现有这样的员工信息表 我们希望按下图的样子统计 按奖金某金额段的人数及金额额度统计. 本例统计 "5k 以下" , "5k – 8k" , "高于 8 ...

  8. 润乾报表与DERBY数据库的创建连接详解

    1. 问题概述 1.Derby数据库的创建过程 2.润乾报表连接Derby数据库展现数据 概述: Derby是Apache Software Foundation (ASF)的一个的孵化器项目.它是由 ...

  9. java web 润乾报表教程_润乾报表开发 基础教程.ppt

    润乾报表开发 --基础教程 主格和附属格 单元格进行扩展的过程中,缺省情况下,相对于其右(下)边的单元格而言,扩展格是主动复制的,被称为其它格(其右/下的格)的主格,而其右(下)的单元格是被动跟随复制 ...

最新文章

  1. 2022-2028年中国汽车橡胶密封件行业市场深度分析及发展趋势分析报告
  2. vue cli3.3 以上版本配置vue.config.js
  3. matlab中统计工具箱函数名大全
  4. scrapy startproject【学习笔记02】
  5. 阿里云肖力:原生安全打造云上绿洲
  6. python小工具自动审单录凭证_跟着老板工作了二十年,最近来了个新员工然后我被开除了...
  7. [转帖]Ipvsadm参数详解(常用命令)
  8. CentOS7和win7双系统启动项
  9. 使用电脑时,眼睛离电脑多远才合适
  10. iOS程序-UIScrollView的基本使用
  11. Linux sort命令浅析
  12. Codeforces Round #322 (Div. 2) D. Three Logos 暴力
  13. 模拟电路实现延时功能
  14. 元器件(Components)安规标准(UL+IEC)
  15. 真值表-Python实现
  16. 星际、魔兽3、红警完全对比
  17. 按图搜索商品获取数据测试
  18. ## DNF地狱猫官方版本公告
  19. 《基于Python的金融分析与风险管理》学习笔记
  20. 杨超越杯编程大赛,参赛作品过100个,工程师评论:杨超越是谁?

热门文章

  1. Java基础——运行时异常和非运行时异常
  2. 【王喆-推荐系统】评估篇-(task3)TensorFlow的模型离线评估实践
  3. 【王喆-推荐系统】(task4)Embedding+MLP模型(模型篇)
  4. 最新区块链项目-芝士小视频
  5. Flutter在苹果手机上运行崩溃事件,iOS 14 崩溃
  6. Python对IP地址列表排序、对列表进行去重、IP地址与MAC地址组合的多个元组的列表排序,对列表内的元组升序和降序排序
  7. c语言结构体定义、输入与输出
  8. bat拷贝与powershell拷贝
  9. 903前端埋点 springboot
  10. PS“无法完成请求,因为智能对象不能直接进行编辑”解决办法