- 产品
- 产品解决方案
- 行业解决方案
- 案例
- 数据资产入表
- 赋能中心
- 伙伴
- 关于
时间:2022-07-22来源:准备胎浏览数:197次
第一次革命发生在报表工具诞生的初期,当时基础类,工具类软件,基本都是国外软件的天下,报表工具似乎也不例外,外国人带着他们的报表工具进入中国,也想像数据库一样,占领和收割国内的庞大软件市场,但是这一次他们折戟了,国外的报表工具不仅没有成功,反而是被国产的工具打的落花流水,甚至连开源免费的也被打趴下了为什么一向厉害的国外软件在报表领域却没有打败国产的呢?
先回顾第一次革命
第一次革命发生在报表工具诞生的初期,当时基础类,工具类软件,基本都是国外软件的天下,报表工具似乎也不例外,外国人带着他们的报表工具进入中国,也想像数据库一样,占领和收割国内的庞大软件市场,但是这一次他们折戟了,国外的报表工具不仅没有成功,反而是被国产的工具打的落花流水,甚至连开源免费的也被打趴下了为什么一向厉害的国外软件在报表领域却没有打败国产的呢?刚进入国内的国外报表软件,其实在前期也打开了一定的市场,形成了一定的规模,知名度也挺高,比如水晶报表,但是很快就漏出疲态,由于产品处于初期阶段,而且欧美人的表格可能也比较简单,这些国外报表工具,使用上很不方便,只能做简单的表格可以看看下面这俩,看着就有点蒙圈,不知道该怎么弄了,完全和我们平时看到的表格不一样,增加学习成本不说,即使学会了也不用,做不了复杂的表格再来说第二次革命
一次革命后,复杂报表的制表方面的难题就基本都解决了但随着行业的发展,我们又慢慢发现,虽然报表工具已经很牛,什么复杂表格都能做,但有些时候,报表开发还是很让人头疼,因为给报表准备数据有时候是一件更困难的事情做过实际项目开发的工程师都知道,应用中的报表,有 80% 的数据来源和计算都比较简单,很多一个简单的 SQL 语句就搞定了,但还有 20% 的情况中,数据准备工作就没有那么好做了,一些过程式的多步骤复杂计算,常常要写很长的多层嵌套的 SQL 或者存储过程才能搞定,如果数据来源再复杂一些,要对各类数据源混算,一些非关系数据库或者文本数据源都不支持 SQL 了,那还得用 JAVA 等语言来写,SQL 10 几行能写完的,JAVA 恨不得写出几百行来,编码难度和效率就更糟糕了然而恰恰是这仅占 20% 的需要硬编码来做复杂数据准备的工作,却占了我们 80% 的工作量集算器 SPL
降低报表数据准备开发难度
比 JAVA 和 SQL 更易写 当前复杂报表的数据准备工作一般是采用 JAVA 或 SQL 完成的,存储过程以及中间表也可以看作是 SQL。SPLSPL 的语法比 JAVA 和 SQL 更为简单易懂,采用 SPL 能在很大程度上简化这些开发量JAVA 等语言没有提供批量数据计算的类库,写个简单的 SUM 也要好几行,更何况分组、连接等运算,而对于过滤、汇总用到的通用表达式计算,基本上是大多数应用程序员无法完成的任务了SPL 则提供了大量与结构化计算相关的基础对象和方法,分组汇总这些只要一句,而且是解析执行的动态语言,可以进行随意的表达式计算。使用 SPL 完成报表数据准备工作要比 JAVA 容易得多,代码也要短小很多,这一点很好理解,就不具体举例了代码短小不仅是写得更快,而且还能容易理解算法和排错,绝大多数报表的数据准备算法可以在一个屏幕内显示出来,可以更直观地理解代码的整体含义。而使用 JAVA 时,一个完整的业务逻辑常常需要几百行代码,翻看到后面时已经忘了前面的了有经验的程序员都知道,SQL 用来实现很零碎的多步运算很不方便,特别是与次序相关的运算,程序员常常要把数据从数据库中取出来用 JAVA 等完成。而 SPL 则正好在这方面做了强化,在分步计算、集合化、有序计算和对象引用等几方面做了完善,对于常用的日期和字串等运算,也比大部分 SQL 提供了更丰富的方法举个例子,我们要算某支股票最长连续涨了多少交易日SQL 的写法 select max(continuousDays)-1 from (select count(*) continuousDays from (select sum(changeSign) over(order by tradeDate) unRiseDays from (select tradeDate, case when closePrice>lag(closePrice) over(order by tradeDate) then else 1 end changeSign from stock) ) group by unRiseDays)SPL 的写法
A | |
---|---|
1 | =stock.sort(tradeDate) |
2 | =0 |
3 | =A1.max(A2=if(closePrice>closePrice[-1],A2+1,0)) |
SPL 简化 SQL 编码的例子很多,有兴趣可以去参考: 4 SPL 方案与案例(http://c.raqsoft.com.cn/article/1647044867607)
不过,需要说明的是,SPL 虽然在大多数情况下的语法要比 SQL 更简单易写,但并不能完全取代 SQL。数据从数据库读出的 IO 成本相当高,有些涉及数据量太大的简单运算,数据读出的耗时远远超过运算本身,这种情况还是放在数据库中运算更合适比报表中计算更广泛 报表工具都可以完成计算列、分组排序等运算,润乾报表还提供了跨行组运算和相对格与集合的引用方案,可以完成更复杂一些的运算报表工具中的运算是一种状态式的计算,也就是把所有计算表达式写在报表布局上,由报表工具根据依赖关系决定计算次序。这种方法好处是很直观,在依赖关系不太复杂时能一目了然地了解各单元格的运算目标但是,在依赖关系较为复杂,数据准备计算需要分成多步时,状态式计算就困难了,要实施过程式计算,经常需要借用隐藏格,隐藏格不仅将破坏状态式运算的直观性,由于状态式计算一般需要全内存处理依赖关系,还会占用更多不必要的内存。而且还有许多运算即使用隐藏格也难以完成比如统计各地区前五的销售业绩,第六名以后全部归并为其他如果不借助数据准备环节,就要在报表中使用隐藏行列手段将不该列出来的条目隐藏,而不能直接过滤掉单纯报表工具实现:
A |
B |
|
1 |
=json(file("d:\\sales.json").read()).sort(amount:-1) |
取数并逆序排序 |
2 |
=A1.cumulate(amount) |
计算累计序列 |
3 |
=A2.m(-1)/2 |
最后的累计值即是总和 |
4 |
=A2.pselect(~>=A3) |
超过一半的位置 |
5 |
=A1(to(A4)) |
按位置取值 |
更多例子可以参考:报表工具怎样使用 Json/XML 的数据(http://c.raqsoft.com.cn/article/1640858385206)
而且一般报表工具使用的数据集都是类似 SQL 返回的那种单层二维表,碰到象 json 或 XML 这类多层数据只能先转换成多个单层数据集,再在报表模板中关联运算拼接成多层报表。而 SPL 可以直接支持多层数据集计算,不需要做这个转换,减少工作量,润乾报表也可以接受 SPL 返回的多层数据集直接按层次呈现,不需要在报表中再做关联类似地,MongoDB 也支持多层数据,也可以用 SPL 直接计算并返回给润乾报表另外数据库还包括 NoSQL 数据库、文件包括 HDFS 文件,对于 SPL 来讲都是数据源。SPL 自有的计算能力可以使这些计算能力不一的多样性数据获得通用一致的计算能力。比如文件几乎没有计算能力,MongoDB 对 JOIN 和 GROUP 运算支持不足,各家数据库对窗口函数的支持程度不同、日期与字串处理能力也普遍不足且风格迥异。采用 SPL 后可以用相对一致的方案来计算,而这将意味着更低的移植成本以及学习难度而且用 SPL 辅助计算后还可以保留非关系数据库原有的优势。比如 MongoDB 的对追加型日志数据的吞吐能力就远远超过普通关系数据库,但结构化计算能力较弱,用 SPL 来弥补后,数据可以继续留在 MongoDB 中,即获得其高吞吐性能也有了结构化计算能力。优化报表应用结构
集算器 SPL 的设计初衷是提升数据准备过程的开发效率,但实际应用下来我们发现,SPL 不仅提升了数据准备的效率,同时还优化了应用的结构,这个能力,也非常有意义解释执行降低应用耦合度 我们知道,JAVA 应用大多数情况是事先编译并静态加载的,也就是要把所有模块一起编译打包后部署,在运行过程中代码就不再改变了。其实 JAVA 也有动态编译和加载的技术,但难度和复杂度都高很多,一般应用程序员很少使用。而且即使采用了动态加载技术,也不能替换已经加载进内存的类,只能不断新增新的类这种机制下,用 JAVA 编写的报表数据准备算法就需要和主应用程序一起打包发布,这会导致报表模块与主应用之间的高耦合性一般来讲,报表的业务稳定性要比主应用差得多,报表变动的频率远远高于主应用,一旦报表的数据来源发生变化,整个应用就得跟着重新编译,无法做到热切换,这种使用体验是很糟糕的如果用 SPL 来实现数据准备算法,就能有效地降低主应用程序与报表功能的耦合度了SPL 写出来的脚本也是类似报表模板的外置文件,不需要和主应用程序一起编译打包,而且它是解释执行的动态语言,在修改时不会涉及主应用程序,只要把 SPL 脚本替换就可以,天然就支持热切换提升报表运算性能
报表的呈现周期中,大致可以分为下图的 4 个环节,4 个环节都有可能造成报表的性能问题,但概率较高的是前两个环节,数据准备和数据传输(图中黄色电池电量图,代表了出问题的程度)开源 SPL 提速保险公司团保明细单查询 2000+ 倍
开源 SPL 提速银行资金头寸报表 20+ 倍
开源 SPL 提速银行 POS 机交易报表 30+ 倍
开源 SPL 提速资产负债表 60 倍提升数据传输的性能 报表项目大部分都是 JAVA 应用,基本都得通过 JDBC 来取数、做数据传输,有时候我们会发现,SQL 很简单,数据库负担也很轻,但数据传输到报表却需要很长时间,传输完成后,报表也算的很快,那就可以判定,就是有些数据库的 JDBC 取数太慢,导致了性能问题我们动不了厂商的 JDBC,那就只能曲线救国,单线程取的慢,如果数据库允许,我们可以尝试多线程并行取,但由于并行取数涉及的数据分段方法和数据库及取数语法需要较复杂代码控制,也不容易做成报表功能,所以目前的报表工具基本都不支持并行取数但在 SPL 中,这却是一个非常普通的功能,下面就是一段 SPL 并行取数的代码,写起来还是很简单的,也容易理解
A |
B |
|
1 |
=now() |
//记录开始时间 |
2 |
=connect("oracle").query@1x("SELECT COUNT(*) FROM CUSTOMER") |
|
3 |
>n=12 |
//设置并行数,根据电脑的物理CPU核数决定 |
4 |
=n.(range(1,A2+1,~:n)) |
//按总记录数和并行数分段,记录本段开头和下段开头数字 |
5 |
fork A4 |
=connect("oracle") |
6 |
=B5.query@x("SELECT * FROM CUSTOMER WHERE C_CUSTKEY>=? AND C_CUSTKEY<?",A5(1),A5(2)) |
|
7 |
=A5.conj() |
//合并取数结果 |
8 |
=interval@s(A1,now()) |
//计算运行时间 |
在数据库负担不重时,并行取数几乎可以让传输效率得到线性的提升
总结
报表工具的两次革命:第一次革命,解决了国外报表工具不好用,做不了复杂报表的难题,重新定义了报表工具的标准,让用户张口就能问:能不能做中国式复杂报表,有没有非线性报表模型,也让国产软件在报表这个领域一直以碾压式的优势走到现在第二次革命,解决了报表外围的数据准备过程 SQL、存储过程、JAVA 难写以及性能低下的难题,同时还优化了报表应用的结构,再一次重新定义了报表工具的标准,让业界都认可报表工具要有一个计算层,也让整个报表的解决方案更完整,有了质的提升。下一篇:企业经营管理一体化...