最近公司要进行大数据的报表统计,主要是从各个维度的基础表中将数据按月、日、周进行统计,起初的小量数据是直接使用sql进行统计语句,并将统计结果插入到各个统计结果表当中,但是这种做法缺点也是很明显的,由于统计的维度高达200个,所以sql语句对于数据库的压力很大,而且统计出来的结果会在程序内存中滞留很久的时间,很容易出现程序内存溢出也会导致数据库的压力增大影响整体系统性能,所以后来经过讨论采用了基于rocksdb作为中间缓存的流式计算报表统计方式。
主要计算逻辑为 批量读取基础表(每一万条或者更多)——》 计算这些数据 ——》计算结果存储到rocksdb当中 ——》等待全部运算结束——》根据存储维度插入到统计表(每一万条插入一次)
通过以上方式进行多维度报表统计的结果就是,
优点:
1、基本上程序的内存使用控制在一个值以下
2、数据库压力也很少,使用主键的查询方式性能很高
3、查询sql简单化,只需要批量查询主键,每次查询一部分数据出来进行运算即可
缺点
1、 计算量很大
2、cpu使用率相对较高
3、rocksdb在中间数据量很大的情况下占用的硬盘空间很大
4、代码相对复杂(利用代码计算统计结果)
批量查询基础表的逻辑代码为
/**
* 传入日期进行流式计算,每天计算一次,并保存
* 这边因为是大数据基础表,所以用的是分表分区查询工具类
*/
@Override
public void calculate(String tableNameTime, String reportTime, List<DataProcessingInterface> dataProcessingInterfaces) throws Exception {
String sql = "select min(id) mid,count(1) cn from tablename where 1=1 and createdate >='"+reportTime+"' and createdate <='" + reportTime + " 23:59:59' ";
Map param=new HashMap<>();
param.put("startTime",reportTime);
param.put("endTime",reportTime+" 23:59:59");
PartSearchSqlUtil partSearchSqlUtil=new PartSearchSqlUtil(sql,param);
partSearchSqlUtil.setSubmeterStartDate("startTime")