在数据库中有一类用于保存中间计算结果的物理表,通常被称为“中间表”。中间表主要跟 OLAP(在线联机分析)业务有关,产生的原因主要有以下几方面。
1. 计算逻辑复杂
在 OLAP(报表或查询)业务中,有些计算逻辑很复杂,每次都从头写会导致报表开发过于繁琐,而且有的计算用 SQL 很难写出来。这时会采用中间表事先计算好,再基于预计算的中间结果开发报表。
计算逻辑复杂常见于报表业务中,以固定报表最为常见;多维分析则比较少见。
2. 查询性能差
当查询涉及的数据量很大或者计算逻辑很复杂时查询性能会很差。为了提升查询性能,增强用户体验,通常会把汇总结果实现计算出来存储在中间表中。基于预汇总的中间表查询速度会快很多。
在实际业务中,大部分提升查询速度的中间表也都是为报表服务的。
3.ETL 过程转存
ETL 过程也会产生中间表。ETL 过程中常常会涉及到数据库的数据,正常的 ETL 过程应当是 E、T、L 这三个步骤逐步进行,也就是先清洗转换之后再加载进数据库,最后在数据库中的只是合理的结果数据。但是,E(清洗)和 T(转换)这两个步骤中会涉及到大量数据计算,而在数据库外实施这些计算很不方便,所以实际情况就会是把涉及到的所有数据都先加载进来然后再进行清洗和转换,ETL 过程变成了 ELT 甚至 LET。事先要加载的这些数据在关系数据库中也必须以表的形式存储,这就使数据库中增加了许多并非最终需要的中间表。
如果观察一下这些跑批任务,你会发现 ETL 任务很多都是为报表业务服务的。
4. 多样性数据源混合计算
另一种情况是多样性数据源造成的,这也是为数据呈现(报表查询)服务的。现代应用中的数据呈现经常会涉及数据库外的数据,目前一般的做法是把库外数据定时导入到数据库中,然后就能和数据库内的数据一起运算产生报表,否则很难实现数据库内外的数据的混合运算。这当然也会让数据库中多了一些表,而且,有些互联网上取过来的数据常常是多层的 json 或 XML 格式,在关系数据库中还要建立多个关联的表来存储,会进一步加剧中间表过多的问题。
通过列举的 4 个中间表产生的主要原因,我们发现一个共同点:中间表大部分情况都是为报表服务的。我们也知道,实际业务中的报表数量非常多,而且报表业务业务不稳定经常会新增修改报表,这会导致中间表数量不断增多。
中间表是一把双刃剑,提供很多便利的同时也会带来一些问题。
我们曾在一个运营商的报表系统中,发现了一个让人吃惊的现象。在 DB2 数据仓库中,有两万多个数据库表!经过深入了解发现,真正的原始数据表只有几百张,剩下的大量的数据库表都是为查询和报表服务的中间表。
像这种系统经过几年乃至十几年的运行,数据库中的中间表越来越多,甚至出现这种上万个的情况并不少见。大量中间表带来的直接困扰是数据库存储空间不够用,面临频繁的扩容需求。中间表对应的存储过程、触发器等等需要占用数据库的计算资源,也会造成数据库的扩容压力。
中间表过多还会带来管理方面的问题,对于成千上万张中间表想要梳理清楚恐怕是一件非常头疼的事情。
那么,是不是可以清理掉一些不用的中间表?一般的结论都是:搞不动。数据库中的中间表是不同程序员制作的,有的是综合查询系统使用,有的是报表系统使用。中间表之间还存在交叉引用,有些程序员看到有别人生成的中间表就直接使用了。有时候一些查询报表已经废弃不用了,但是对应的中间表没人敢删,因为不知道删掉之后会影响其他什么查询或者报表。
很多情况下,项目组只好为了越来越多的中间表去扩容数据库。但是数据库的扩容成本太昂贵了:不管是换更强的服务器(纵向扩容),还是增加数据库服务器的节点(横向扩容),都不便宜。
总结来说,中间表会带来管理、容量和性能三方面的问题。
可以很容易想到的方式是使用库外文件存储中间表数据,这样中间表脱离了数据库就不会对数据库再产生影响。但是,在实际应用中这种办法却很少使用。为什么呢?
我们知道,中间表是要再计算的,基于中间表查询的报表还要进行数据过滤,有的还要再次汇总,还可能涉及关联计算,这些操作在数据库里通过 SQL 完成很简单。但是文件没有计算能力,要实施这些计算只能硬编码,用 JAVA 来做,使用 JAVA 来做集合运算又非常麻烦,远没有数据库(SQL)方便。所以采用文件存储中间表的方式使用并不广泛,主要是由实现复杂度过高导致的。
那还有什么好的方式呢?
使用支持文件源的报表工具
既然中间表大部分是为报表服务的,而通过将中间表外置到文件中可以解决中间表带来的这些问题,那么直接使用支持文件源的报表工具是否就可以了呢?
答案是肯定的。
我们来看一下要实现这个目标,报表工具要具备哪些能力?
(1) 丰富的计算类库
要解决文本计算难的问题,报表工具要提供丰富的计算类库,除了能完成所有数据处理任务(都能算)以外,还要实现简单,这是基础,太复杂了没法用;
(2) 多样性数据源接口
支持多样性数据源以后,就可以不用通过数据库中转直接读取多样性数据源数据出报表;
(3) 异构数据源混合计算能力
提供多样性数据源接口后,还要能够进行异构源间的混合计算,这样就可以彻底解决掉多样性数据源带来的中间表问题;
(4) 高性能
除了实现简单以外,计算性能也要有保障,从而满足前端报表查询的性能需要。
具体实现上可以在报表工具中增加计算模块来对接“库外中间表”,结构类似这样
其中库外中间数据文件可以采用本地文件,也可以使用网络或分布式文件系统,或其他数据源。
要解决中间表问题,需要报表工具强化自身的计算能力才能实现!
参考资料:
【数据蒋堂】第 14 期:计算封闭性导致臃肿的数据库
【数据蒋堂】第 15 期:开放的计算能力为数据库瘦身
有效减少数据库中间表的报表开发方法
为什么会有这么多中间表?