秒级展示的百万级大清单报表怎么作

数据查询业务中,有时会碰到数据量很大的清单报表。因为用户输入的查询条件可能很宽泛,所以会从数据库中查出几百上千万甚至过亿行的记录,常见的包括银行流水记录,物流明细等。呈现时若是等着把这些记录所有检索出来再生成报表,那会须要很长时间,用户体验天然会很是恶劣。并且,报表通常采用内存运算机制,大多数状况下内存里也装不下这么多数据。因此,咱们通常都会使用分页呈现的方式,尽可能快速地呈现出第一页,而后用户能够随意翻页显示,每次只显示一页,也不会形成内存溢出。前端

传统分页呈现的实现,通常都会使用数据库的分页机制来作,利用数据库提供的返回指定行号范围内记录的语法。界面端根据当前页号计算出行号范围(每页显示固定行数)做为参数拼入 SQL 中,数据库就会只返回当前页的记录,从而实现分页呈现的效果。web

不过,这样作会有两个问题:数据库

1. 翻页时效率较差缓存

用这种办法呈现第一页通常都会比较快,但向后翻页时,所使用的取数 SQL 会被再次执行,而且将前面页涉及的记录跳过。对于有些没有 OFFSET 关键字的数据库,就只能由界面端自行跳过这些数据(取出后丢弃),而像 ORACLE 还须要用子查询产生一个序号才能再用序号作过滤。这些动做都会下降效率,浪费时间,前几页还感受不明显,但若是页号比较大时,翻页就会有等待感了。并发

2. 可能出现数据不一致app

用这种办法翻页,每次按页取数时都须要独立地发出 SQL。这样,若是在两页取数之间又有了插入、删除动做,那么取的数反映的是最新的数据状况,极可能和原来的页号匹配不上。例如,每页 20 行,在第 1 页取出后,用户尚未翻第 2 页前,第 1 页包含的 20 行记录中被删除了 1 行,那么用户翻页时取出的第 2 页的第 1 行其实是删除操做前的第 22 行记录,而原来的第 21 行实际上落到第 1 页去了,若是要看,还要翻回第 1 页才能看到。若是还要基于取出的数据作汇总统计,那就会出现错误、不一致的结果。webapp

为了克服这两个问题,有时候咱们还会用另外一种方法,用 SQL 游标从数据库中取数,在取出一页呈现后,但并不终止这个游标,在翻下一页的时候再继续取数。这种方法能有效地克服上述两个问题,翻页效率较高,并且不会发生不一致的状况。不过,绝大多数的数据库游标只能单向从前日后取数,表如今界面上就只能向后翻页了,这一点很难向业务用户交代,因此不多用这种办法。异步

固然,咱们也能够结合这两种办法,向后翻页时用游标,一旦须要向前翻页,就从新执行取数 SQL。这样会比每次分页都从新取数的体验好一些,但并无在根本上解决问题。jsp

润乾报表方案

下面介绍的润乾报表方案,提供的大报表功能能够支持海量清单报表的秒级查询。在这个方案中,取数和呈现采用两个异步线程,取数线程发出 SQL 后不断取出数据缓存到本地,由呈现线程从本地缓存中获取数据进行显示。这样,已经取出并缓存的数据就能快速呈现,再也不有等待感;而取数线程所涉及的 SQL,在数据库中保持同一个事务,也不会有不一致的问题,前面提到的两个问题所有得以完美解决。高并发

同时,借助集文件存储格式,报表还能够按行号随机访问记录,而不用每次经过遍历查找数据。也就是说,这种存储格式支持跳转到任意页访问,从而极大地改善了用户体验。不过,因为采用了异步机制,页面端显示的总页数和总记录数会随着取数过程不断变化。

大清单报表运行原理:

1png

须要注意的是,大清单报表中用到的异步机制和集文件存储都是在集算器的基础上实现的,所以该功能须要“集成集算器”功能支持,并不包含在润乾报表基础版中。

下面经过举例来讲明润乾海量大清单报表(如下简称:大报表)的开发使用过程。

SQL 源大报表

首先来看一种最基础的大报表,即报表数据来源于数据库的状况。例子中咱们须要根据日期范围查询订单表的交易信息,因为数据规模较大,所以须要使用大清单报表呈现。

制做报表模板

与普通报表开发同样,设置参数、准备数据集、绘制报表模板。

报表参数为查询日期起止:

2png

数据集根据参数查询订单表 SQL:

3png

报表模板:

4png

设置大数据集

与普通报表不一样,须要在润乾报表属性(报表 - 报表属性)中设置“大数据集名称”,指向数据集 ds1,直接利用 SQL 完成异步取数。

5png

设置完成后,在报表设计器 IDE 中便可浏览报表:

6IDEpng

发布到 WEB

与普通报表发布相似,大清单报表也经过 JSP 以 tag-lib 的方式发布。

<report:big name="report1" reportFileName="<%=report%>"

 needScroll="<%=scroll%>"

 params="<%=param.toString()%>"

 exceptionPage="/reportJsp/myError2.jsp"

 scrollWidth="100%"

 scrollHeight="100%"

 rowNumPerPage="20"

 fetchSize="1000"

 needImportEasyui="no"

 /> 

<report:big name="report1" reportFileName="<%=report%>"

 needScroll="<%=scroll%>"

 params="<%=param.toString()%>"

 exceptionPage="/reportJsp/myError2.jsp"

 scrollWidth="100%"

 scrollHeight="100%"

 rowNumPerPage="20"

 fetchSize="1000"

 needImportEasyui="no"

 />

其中 rowNumPerPage 属性为每页显示记录数;fetchSize 为每次从数据源读取的数据量。完整发布的 JSP 能够参考报表安装目录下的样例文件:[report\web\webapps\demo\reportJsp showBigReport.jsp]。

WEB 端呈现效果:

7webpng

能够注意到,右上角的页码和总记录条数随着异步线程不断读取数据而不断变化。

除了展示,在润乾报表中还支持对大清单报表导出 Excel 和打印。

导出

8png

打印

9png

非 SQL 源大报表

当海量数据来源非 RDB 时,因为没法利用数据库分页,所以没法经过 SQL 实现异步大报表。针对这一问题,润乾报表的大报表方案中,采用了两阶段异步线程,其中由集算器定义取数线程负责从非 RDB 数据源取数并缓存数据,再由呈现线程负责读取缓存并分页展示。

       下面以文件数据为例,说明非 RDB 数据源的大报表开发过程。例子中的卫星数据以文件(CSV)方式存储,数据规模较大,是典型的非 RDB 数据源。如今咱们要按照日期查询某日风速、温度等明细信息。

报表数据准备

       首先,咱们借助润乾报表的集算器数据集读取文件数据,并为报表返回游标。集算器 SPL 脚本以下:

A
1 =file(“source.csv”).cursor@t(;,",")
2 =A1.select(时间 ==   d_time)
3 return A2

A1 创建文件游标;

A2 在游标执行时对数据进行过滤(此时游标还没有执行,数据并未取出);

A3 返回游标过滤结果,为报表提供数据。

将 SPL 脚本存储为 bigReport-file.dfx,并在报表中做为数据集引入:

1png

设计报表模板

       接下来,咱们根据所准备的数据制做报表模板:

2png

同时设置大数据集:

3png

发布到 WEB

而后,将作好的报表发布到 WEB 端:

4png

     是否是很简单? 这个例子显示了在开发报表时若是涉及海量非 RDB 数据,润乾报表能够借助集算器对多种数据源类型的支持能力,实现大报表开发与呈现。

使用大报表注意事项

       上面介绍了开发大报表该有的正确姿式,但任何功能都不是万能的,使用大报表也有须要注意的地方:

一、不排序

大报表的数据集都比较大,若是在乎响应时间(谁会不在乎呢),那么应该尽可能不对数据集进行全表排序(注意我说的是全表排序),毕竟,等排完序再呈现,时间已通过去好久了……

二、不适合高并发场景

大报表采用异步机制,将数据分批加载到内存再交给前端呈现,减小了内存占用,但同时增长了 CPU 和磁盘 I/O 负载,并发高时 CPU 和硬盘可能成为瓶颈从而影响呈现效果,所以大报表不适合高并发的场景。

       本文主要介绍了 RDB 和非 RDB 数据源状况下大清单报表的开发方法,在下一篇《百万级分组大报表开发与呈现》中,咱们将进一步介绍带有汇总值的大报表和分组大报表的实现过程。

相关文章
相关标签/搜索