在公司做B端业务时,报表功能是一个经常会面临的需求,有些时候需求很离谱,产品不仅仅要求报表出的数据准确,还要查询数据快,还要支持实时性,经典啥都需要。
问题分析
报表中数据的查询大多数是需要查询大量的数据并进行汇总,查询快和报表表面看起来就是天然的冲突关系。
但是我们仔细分析问题还是有解决方案
首先报表数据一般来说是根据业务主体+时间范围去做,比如说一个餐厅+日周月,其次这种做报表的数据一般是流水数据,也就是说在数据最后的变动有个截止时间,不可能我这个月去改上个月的流水吧。
查询时间
所以基于数据不可变这个特定,我们可以进行先行聚合 对流水数据做小的业务颗粒度进行聚合,比如说按天。 按月按周查询,业务代码中在单独聚合就行了,先行聚合后查询时间相比于直接查流水会大幅提高
实时查询
在来看实时查询的需求,这个时候我们数据先行聚合的表没有生成,这时候就只能去流水拿数据了,所以在页面上 用户数据 = 先行聚合数据+流水数据
流水数据的优化:
报表数据往往基于多个业务生成,如果我们更近一步,还可以对实时数据进行优化,多个业务数据可以使用多线程+coutDownLatch 来实现 (为啥不使用forkJoin?—用的不太熟)
查询报表的优化:
应报表数据是不变的,所以可以考虑针对不同的时间整数做redis缓存,比如说查询2024年8月10日数据到2024年8月17日12 点数据,那么就可以对10日到17天的数据进行缓存,在页面上用户一般会单独去选时间
数据汇总优化:
同报表优化,对部分时间做缓存
写业务代码的时候,可以考虑将相同的逻辑流程封装到一个模板方法中,子类继承这个方法就行
1、按时间的分页方法实现
2、数据加法的抽象方法
3、报表查询缓存
4、报表DB数据查询抽象
5、实时数据查询抽象