报表工具支持多数据源的方法

报表的数据来源非常丰富,理论上任何数据源都可能同时作为报表的数据源来源,RDB、NoSQL、CSV、Excel、Json、Hadoop 不一而足,这就产生了报表开发中的多源问题。如何解决多源带来的一系列问题?本文将从以下几个方面来考察报表工具对多数据源支持的方法,并加以点评。

  • 如何连接这些数据源?
  • 连接了如何混合使用?
  • 多源混合计算支持程度如何,能够完成复杂计算?
  • 性能如何?

多源可能是多个同构的数据源,也可能是多个异构的数据源,不同的场景有不同的处理方法。

如何连接多样性数据源问题可以参考《报表工具应对非关系数据库数据源的方法》,这里不再做过多讨论。

数据库跨库查询

一些数据库本身提供了跨库查询的方法,如 Oracle 的 DBLink,MySQL 的 FEDERATED 引擎都可以实现多个同类数据库的混合查询。如果报表开发中面对的多个数据源是同构的,可以采用数据库自身的跨库查询能力来应对多源问题。

不过这种方法也有很多缺点,明显的是对异构数据源支持不好,无论是 DBLink 还是 FEDERATED 在异构源方面表现都不够稳定,甚至 FEDERATED 还要求表结构完全一样(FEDERATED 会在本地创建表定义,数据文件存在于远程数据库中)。其次这种方式会占用大量数据库资源而且性能很差。还有一些缺点,包括:数据传输不稳定、不支持大对象操作、容易出现错误稳定性差、可扩展性低等等问题。

与跨库查询类似,当数据源是 csv、Excel、json 或者 Spark 时可以使用对应的计算引擎进行多源混合计算,比如 Microsoft text/xls driver 可以实现多个 Excel 之间的关联计算,也可以关联多个 txt/csv/tsv 文件(但不直接支持 Excel 和 csv 关联);Spark SQL 也可以实施跨源查询,不过这些方式都无一例外要求数据源同构或仅限几种相似的数据源才能关联计算。

此种方式主要依赖数据库 / 计算引擎的计算能力,算法实现上通常采用 SQL 实现,因此复杂计算的支持程度取决于对 SQL 的支持程度。Oracle 提供的函数更丰富计算能力也更强,MySQL 则略弱,而其他计算引擎的能力就参差不齐了,大部分都比较弱。

本身只能解决同构数据源的查询就已经大大限制了使用场景,还存在很多其他问题使得这种方式在解决报表多源问题时作用十分有限。

数据同库

对于异构源混合查询,目前较多采用的方式还是将异构源转为单源再使用,通常是将其他数据源的数据导入 RDB 中,借助 SQL 的能力完成数据查询。同步数据的方法有很多种,自己编写脚本、使用 ETL 工具或者使用像 Hevo、Knowi、Stich 这样的自动同步工具都可以实现。

这种方式简单粗暴,采用迂回的策略解决了多源问题。但缺点也很明显,这种方法的代价显然非常大。且不说将这些数据导入目标数据库能否容纳(数据库容量问题)以及带来的查询性能问题,数据同步是时间成本也非常高。要知道报表查询的数据范围可能非常大,数据源种类也很多,这些数据都导入到数据库时间长、占用空间大,如果用到哪些导哪些又会影响报表查询速度。如果还涉及数据变化,那数据同步成本就更高了,而且数据导出导入通常只会定时执行,这样也就丧失了数据的实时性,而报表经常要求查询实时数据。

很多时候这种方式无异于建设一个企业级数据仓库了,即使这样也不能充分满足数据实时性的问题,更无法利用各种数据源自身的优势了。

无论是采用数据库跨库查询还是数据同步到一个数据源本质上并不是报表工具的能力,下面介绍两种报表工具自身的多源能力。

报表数据集关联

有些报表工具提供了关联数据集(Joint Data Set)功能,允许用户将其他数据集关联起来形成新的数据集从而完成多数据源数据整合。使用时,先针对每个数据源建立数据集,然后再通过“关联数据集”将这些数据集关联起来从而形成一个新的数据集这样就实现了多源混算。不过遗憾的是,有的报表(如 BIRT)仅支持两个数据集联接,如果有多(N)个数据源需要两个两个逐个联接,这要建立 N-1 个数据集了,不仅开发维护是个问题,性能也非常差。此外,关联数据集只支持单字段关联,不支持两个字段以上的等值联接(只支持等值联接)。不仅如此,关联数据集的参数来源于被关联的各个成员数据集,关联数据集的参数只允许查看不能修改和删除,如果成员数据集之间使用了同名参数(很有可能出现)还会出现冲突,用起来可谓限制多多。

因此,“关联数据集”功能十分有限,且性能表现不佳,只能应付一些简单多源混算场景。而且并不是所有报表工具都提供了这个功能,通用性要差一些。

报表表达式关联

另外一些报表工具的多源支持采用单元格表达式来实现,具体做法是在报表中分别针对不同的数据源建立多个独立的数据集,这些数据集在数据准备阶段毫无关系(跟上面的关联数据集不同),在设计报表呈现模板时将各个数据集填入不同片区,然后通过报表函数进行关联。如:dsDB.select(dsDBField,ID==A2),其中 A2 是另外数据集(dsCSV)片区的格子名称,其表达式是:dsCSV.select(ID),两个数据集通过 ID 字段关联展现在报表的不同片区 / 列上。

这种方式的好处是不管有多少个数据源,在数据准备阶段独立准备就好,在呈现模板中这些数据集等同使用,通过表达式关联即可,有多少个都没关系,报表开发和维护都非常方便。

缺点主要有三方面。第一只能单独计算每个数据集的数据,无法将数据先混合再计算,比如两个数据源分别存储了历史订单数据和当期订单数据,现在想要按所有订单的客户汇总订单额,通过报表表达式就无法完成了(上面的关联数据集反倒可以)。第二计算支持有限,报表工具自身的计算能力往往非常有限,加上报表呈现模板的样式也会限制计算的灵活性,这就导致很多计算在表达式中无法完成。第三性能较差,在呈现模板中多个数据集关联往往采用顺序遍历的方式,时间复杂度是平方级的,如果关联的数据集数据较多性能会很差。

集算器 SPL

集算器是专业的开源数据处理引擎,除了可以对接几十种数据源,其本身具备很强的计算能力,通过独立的脚本语法 SPL,可以很方便地完成多源混合计算。集算器提供了标准 JDBC 和 ODBC 接口供报表工具调用 SPL 的计算结果。

集算器 SPL 类似加强型的关联数据集,它不挑数据源类型,同构异构均可,实施关联以及后续计算也很强大。比如 SPL 实现 MongoDB 和 CSV 关联可以这样写(cross.dfx):

A
1 =mongo_open("mongodb://127.0.0.1:27017/mongo")
2 =mongo_shell(A1,"Orders.find()").fetch()
3 =file("Employee.csv").import@tc()
4 =mongo_close(A1)
5 =join(A2,SellerId;A3,EId)
6 =A5.new(_1.OrderID,_1.Client,_2.Name,_2.Gender,_2.Dept)

可以注意到第三行(A3)的数据来源 CSV,如果来源 RDB 可以写成:

=db.query@x(“select * from Employee”)

后续的计算脚本一模一样。集算器提供了不依赖数据源的完备计算能力,这是上面几种方式所不具备的。

然后在报表工具建立集算器 JDBC 数据源就可以使用了,如普通数据库一样。在报表数据集中通过类似访问存储过程的方式调用 SPL 脚本,完成 MongoDB 与 CSV 的关联计算,如:

call cross()

其中,cross 为上述 SPL 脚本名称(cross.dfx)。

集算器 SPL 可以充分利用各种数据源自身的优势,RDB 计算能力强但 IO 传输慢,编写 SPL 时就可以让 RDB 多做一些计算再读取数据,NoSQL 的 IO 吞吐能力强但计算能力弱,就可以把数据取出再计算,非常灵活。直接使用各类数据源数据实时性也高,可以很好满足报表对数据实时性的要求。

同时 SPL 还拥有大数据计算能力,有序运算、外存计算、并行计算等可以应对绝大部分大数据场景,为报表工具快速输出结果集。

在性能方面,多数据源关联时采用更高效的 Hash Join(有多种关联方式供选择),运算效率也更高。

集算器 SPL 支持的数据源有几十种,这些数据源都可以在 SPL 中进行混合计算。目前支持的部分典型数据源列举如下:

  • 阿里云
  • Cassandra
  • 多维数据库
  • ElasticSearch
  • Ftp
  • Hbase
  • Hdfs
  • Hive
  • Influxdb
  • Informix
  • Kafka
  • MongoDB
  • Redis
  • Salesforce
  • Sap
  • Spark
  • Webcrawl
  • Webservice
  • YModel
  • Zip

综合比较这些报表工具支持多数据源的方法,借助数据库的能力总体看代价过高,无论是配置维护跨库查询支持还是数据同库,而且使用场景非常有限;通过报表工具自身的能力也只能应付一些简单的场景且性能不高。开源的集算器 SPL 数据源支持丰富、关联计算简单、具备独立的计算能力可以实施复杂计算、支持大数据等,目前看来是解决报表多数据源场景较廉价快捷的解决方案。