领读|解决方案介绍--报表产品的福音,报表加速领域“黑科技”

关键字:报表、集算器

引子

访问大数据,报表速度慢的问题基本上都会遇到。怎么解决?在搭建报表平台时,经常遇到这个问题,通常哪些厂商会给出如下一些角度来解决问题:

  • 报表执行过程

  • 优化报表取数

  • 优化报表计算时间

  • 巧用参数注入

  • 巧用相邻连续分组

  • 数据集缓存与共享

  • 启用行引擎执行层式报表

  • 单数据集分页SQL实现层式报表

  • 多数据集实现层式报表

  • 修改缓存路径

  • 优化调用Oracle存储过程

  • 服务器内存修改

  • 考虑使用集群

......

但是,然并卵,经常碰到的情况是,仍然无能为力!所以,还有这样的建议存在:

下面是比较灰心的无奈:

再来一个更痛苦的:

或者可以转嫁给DB?

还有提出提升服务器配置和网速的建议的。

朋友反复在尝试,当结果发现这些建议并不怎么样?

笔者在网上看到这样一篇博客:“大数据量报表系统的改进方案”倒是写的比较有意思,原文可以参见:https://blog.csdn.net/zollty/article/details/53958422

背景

目前市面上大部分的报表厂商都集数据计算和数据呈现于一体,润乾报表和帆软报表是商业的固定报表系统产品,Smartbi和帆软BI是商业的自助分析报表系统产品...... 大家的产品同样是以java语言、jvm为基础,提供可视化开发环境,并降低报表开发人员的技术要求。

而润乾集算器则是定位于商业的数据计算引擎产品,在项目实践过程中,我们发现,润乾的集算器与上述各类报表存在较大的互补性,从而大大提高各类报表工具的计算效率,通常可以提高报表计算效率10多倍到上百倍。

  • 一般的报表工具都没有计算层,都依赖数据库、Java或者报表本身很弱计算能力,这也是报表慢的一个主要原因。如果在报表产品中调用集算器,引入了独立的数据计算处理单元—集算器,在数据计算时可以通过更加高效的数据存取方式进行数据查询,还可以通过并行计算实现多线程取数、多线程运算,在报表数据集较多(大于2个)时,并行运算性能更佳。同时,集算器可以替代java自定义程序,复杂SQL,复杂存储过程,提高程序运行效率,改善由于出错处理能力不足带来的程序运行风险。

  • 集算器为报表产品准备数据集,用报表产品集成集算器,让集算器独立成为报表的计算单元,展现时采用报表工具来展示页面;

  • 在报表中的单元格表达式中编写的计算逻辑可能会导致数据集多次重复遍历,格间计算,也会影响性能。集算器是以开发语言的形式提交用户使用的数据计算工具,在集算器中可以很方便地进行分步运算、编写并行程序、读写数据库或数据文件、实现复杂的业务计算逻辑等工作。

解决方案

1、报表系统架构

采用集算器辅助报表产品的报表系统结构图如下:

报表的本职工作其实应该仅仅是数据呈现而已,而报表所不擅长的计算则由更专业的计算引擎-集算器,集算器就是一款专业的可以替代SQL和JAVA的更优的数据计算工具。

引入数据计算层-集算器的数据流向

内存计算:数据读入集算器的内存

流式计算:数据一点点读入集算器,边读边计算

外存计算:数据定期导出到文件系统中缓存,集算器实施外存计算

报表数据计算层的意义

比Java和SQL更易写,集算器语法优势

当前复杂报表的数据准备工作一般是采用Java或SQL完成的,存储过程以及中间表也可以看作是SQL。集算器的语法比Java和SQL更为简单易懂,采用集算器能在很大程度上简化这些开发量,集算器采用集合化语法,代码要比没有直接提供结构化计算的程序更加短小。

集算器的代码比Java也要短小很多,这样不仅是写得更快,而且还能容易理解算法和排错,绝大多数报表的数据准备算法可以在一个屏幕内显示出来,可以更直观地理解代码的整体含义。

集算器除了模型上的优势外,在日期和字串等运算,也比大部分SQL提供了更丰富的函数。许多情况用SQL也不是写不出来,但不能直接按自然思维实现,很费脑筋,这种代码放时间长了程序员自己都会忘了是怎么写出来的,给将来的维护也造成麻烦。集算器代码则符合自然思维习惯,即使是与SQL相同的思路也能更清晰地表达,更容易理解和维护。

多样性数据源及跨库计算

现在有许多报表的数据源并不只来源于关系数据库,还可能是NoSQL数据库、本地文件、从WEB上传来的数据等。这些非关系数据库的数据源缺乏标准的数据获取接口和语法,有些甚至没有最基本的过滤能力。而计算报表时总还要进行一些过滤甚至关联运算,虽然报表工具一般都能提供这些计算能力,但由于都是内存计算,只适合于数据量较小的情况,数据量较大时就会导致容量负担过重。大多数报表工具也不能很好地处理象json或XML这种多层数据,也没有灵活编码能力以登录远程WEB服务获取数据。

如果采用集算器准备数据,则可以直接用这些非数据库数据作为数据源去生成报表,不需要导入数据库的过程,充分利用现有数据源的优势,减少开发工作量。

集算器自有的计算能力可以使这些计算能力不一的多样性数据获得通用一致的计算能力;而这将意味着更低的移植成本以及学习难度。

解释执行降低应用耦合度

Java应用大多数情况是事先编译并静态加载的,也就是要把所有模块一起编译打包后部署,在运行过程中代码就不再改变了。

一般来讲,报表的业务稳定性要比主应用差得多,报表变动的频率远远高于主应用,好的体系设计应当能把报表模板独立出来降低整个应用的耦合性。但是,一个完整的报表由报表工具开发的报表呈现模板和Java开发的数据准备算法构成,报表修改时需要同时改变这两部分,报表模块和主应用的耦合度就会很高。因为报表模板一般保存在文件系统中或有时在数据库中,而数据准备算法却要打入了主应用程序包,存放和管理机制都不一样,这样要保持两者一致就相当麻烦了,报表模块很难独立出来。

Java大多是静态加载的,报表数据准备算法有修改后会导致整个应用重新编译部署,很难做到热切换,如果用集算器来实现数据准备算法,就能有效地降低主应用程序与报表功能的耦合度了。

集算器写出来的脚本也是类似报表模板的外置文件,不需要和主应用程序一起编译打包,而可以和报表模板一起放在文件系统中管理维护,报表模块可以独立出来。

集算器是解释执行的动态语言,在修改时不需要涉及主应用程序,只要把集算器脚本替换就可以,天然就支持热切换。

算法外置减少存储过程

在体系结构方面用存储过程准备报表数据和用Java程序是类似的,也会造成耦合度高的问题,只是从报表模块与主程序之间的耦合变成的报表模块与数据库之间的耦合。

存储过程存放在数据库中,报表模板放在文件系统中,保持两者同步修改依然很麻烦。

存储过程修改时需要申请一定级别的管理员权限做重编译,虽然不象Java那样难以做到热切换,但数据库高权限的频繁使用又会带来安全隐患。

比Java更糟糕的是,数据库及其中的存储过程可能被多个应用共享,如果管理不善,很容易造成多个应用之间的高耦合,时间长了会搞不清楚某个存储过程在被哪些应用调用,越来越混乱。

同样地,采用集算器也可以极大程度地减少数据库中的存储过程,算法外置后与报表模板一起存放管理,完全归属于报表模块,不仅降低与应用其它部分的耦合,更不会造成与其它应用的耦合。

实际上,存储过程本身编写难度并不小,遍历式计算代码的性能也不佳,而且可移植性很差,原则上在报表业务中应当尽量少用存储过程。

替代报表计算

减少隐藏格

报表中通常使用隐藏格来保存中间结果,而进一步获得分步计算的再引用。如果一个报表携带大量隐藏格,必然对性能产生很大影响。这是因为大量隐藏格会占用内存、降低运算速度。而且隐藏单元格除了单元格值外,还记录了很多显示属性值,比如:字体、颜色、显示方式等等。虽然单元格隐藏了,但是这些属性还在,如果带着这些属性计算,也会影响计算速度。

使用集算器事先准备数据则没有这些问题,过程式计算可以方便地复用中间结果,只进行纯粹的数据计算,不涉及隐藏格和外观属性,内存使用效率更高。

控制SQL执行路径

数据库本身的性能无法被报表工具以及其它数据库外部的技术手段优化,只能想办法优化SQL的写法。不过,还是有些场景可以使用集算器提高数据库相关的性能。

SQL不提倡分步的语法让程序员实施干预也相当困难。集算器提供分步的过程计算,充分利用集算器的离散型集合模型。分步执行,控制SQL的执行,集算器就可以自由控制执行路径,部分运算移出数据库实施,起到性能优化的效果。

内存共享

对于高并发报表,利用集算器的内存共享机制,将报表用到的数据缓存在内存中,几个报表可以共享这份内存中数据。从内存中计算不仅能获得数倍于数据库或文件的访问性能,而且可以更方便地实施并行计算,充分利用现代CPU多核的优势,而集算器编写多线性并行计算代码也是非常简单的。

对于这种场景,还可以采用集算器的内存字节表的方式来提高Java内存利用率,数据加载成字节,在使用时才对象化。牺牲大约30%的性能,但可以将Java的内存利用率提高3至5倍,使用内存后,即使牺牲掉30%的性能也仍然远远比数据库和文件等外存更快。

高性能算法

集算器提供了面向数据特征的函数和离散数据集模型,主要体现在:集合化、离散性、分组子集、有序聚合、逆分组、跨行引用、有序分组、位置利用、多级游标、有序游标、列间统计、通用转置、转置计算、文本解析、外键指针化、维表内存化、外键序号化、内存利用率、多线程并行、游标复用、分段并行、有序利用等技术上。

T+0报表

要实现T+0全数据量的实时报表,通常的办法是把部分历史数据被移出来做个分数据库,这样可以保证交易系统的正常运转,但要实现T+0报表就麻烦得多,会涉及到跨库运算。

许多数据库都支持跨库运算,但一般都要求同类型的数据库,但历史数据和当期交易数据的要求不同,数据量更大但不要求事务一致性,很可能使用另一种数据仓库来存储。即使是同构的数据库,数据库的跨库运算的方法一般也是将另一个库中的数据表映射成本库数据表,实际运算还是一个数据库在做,而且还多出许多数据传递的通讯成本,性能和稳定性都不好。

使用集算器就可以很好地完成这个混合计算任务了。

集算器自己有计算引擎,不依赖于数据库,各个数据库内的数据计算仍由各库进行。集算器可以使用多线程向各数据库同时发出SQL语句,由这些数据库并行执行,将各自的运算结果返回到集算器再汇总处理后传给报表工具去呈现。

这种机制还方便横向扩展,历史库可以有多个,是否同类型的也无所谓。

集算器还有服务器方式的集群运行模式,在集算服务器的支持下,历史数据不必一定存放到数据库中,还可以存储在IO性能更好的文件系统中,配合集群计算,可以在更低的成本下获得更好的性能。

总结

报表产品和润乾集算器产品结合,发挥两者的优势。集算器除了可以提升报表运算性能外,它的价值还体现在它可以优化报表的应用结构。刚才说过,通常我们会用JAVA程序做数据计算准备,这样就要求我们的JAVA程序必须和主程序一起打包编译,这样做会造成应用耦合度高,并且在数据准备算法有修改后,整个应用要再次编译并重新启动,不能做到热切换,而集算器支持模块化管理,集算器的计算脚本可以和报表模板一起管理维护,并且支持集算脚本的热切换。而用SQL做数据计算过程中,存储过程和中间表是不可避免的,这样长此以往会造成数据库压力大,集算器可以将数据外置后,给数据库减负。同时,集算器还支持使用多样性数据源,做到扬长避短,充分利用各数据源优势,例如利用非关系型数据库的高IO吞吐,分布式文件系统的容错机制以及关系型数据库的结构化计算能力等。

总之,现在再遇到报表性能问题,我们就要辩证的看问题,报表的问题就去优化报表,计算的问题就去优化计算。哪疼医哪才是解决问题的王道。

(0)

相关推荐