关于java报表的一些经验。

本文讨论了在处理大数据报表时遇到的挑战,包括多表联合查询、按天统计的问题。分析了两种策略:历史表插入和按天切片统计。第一种策略在数据量增加后导致查询效率低下,且与业务代码高度耦合。第二种策略虽然有冗余数据,但索引优化和代码耦合性更优。作者建议采用第二种方案,并强调报表统计应避免逻辑删除字段,以提高查询速度。
摘要由CSDN通过智能技术生成

一、项目场景:

需要做一个报表,多表联合查询,并且数据量都在几十万到百万以上。


二、问题描述

2.1

例如,做一个报表,游戏报表,假如一个游戏有关卡表gate,关卡内含有任务表task,这时候需要按天统计,一个人在哪一天通关了什么关卡,各个关卡任务的完成情况。
在这里插入图片描述
这时候,还会有要统计人的通关情况还需要,gate_user 表,task_user表

2.2

这时候如果不考虑按天切片,我们可以得出这样的sql

select *from gate_user user left join gate  gate on user.gateId=gate.id 
where gate.status ='已完成'.

如果要按天完成,这时候有两种方案,

2.2.1 关卡或者人变动的时候插入历史表,

也就是有 gate_user_his 和 gate_his,然后关卡变动就往这两个表插数据,
然后查询的时候取最新的记录。

SELECT
	*
FROM
	(
		SELECT
			user.*
		FROM
			gate_user_his user
		INNER JOIN (SELECT max(insertTime)) inserttime,
		user1.id,user1.userid
	FROM
		gate_user_his user1
	GROUP BY
		user1.id,user1.userid) user1 ON user1.id = user1.id
	AND user.inserttime = user1 .inserttime and user.userid=user1.userid
	) user
LEFT JOIN (
	SELECT
		gate.*
	FROM
		gate_his gate
	INNER JOIN (
		SELECT
			max(inserttime) inserttime,
			gate.id
		FROM
			gate_his gaet1
		GROUP BY
			gate.id
	) gate on gate .id= gate1.id and gate.inserttime= gate1.inserttime
) gate gate ON USER.gateId = gate.id
WHERE
	gate. STATUS = '已完成'.

2.2.2 按天切片统计

该种方案,每天凌晨把上一天的数据丢一份到历史表里面,
select *from gate_user_his user left join gate_his gate on user.gateId=gate.id
where gate.status =‘已完成’.
and inserttime=‘统计日期’

原因分析:

1.我当时考虑到按天每天塞一份数据,会有很多冗余的数据,而且(关卡X任务X人数)user_task表数据会非常多,采用了第一种方案,
2.然后数据量一上来,就查不动了,不管加索引还是怎么优化都不行,而此时代码已经写了很多,很难再改了。
3.而且变动的时候插入,和业务代码高度耦合,很容易出问题,这也是一大缺点。
4.sql 复杂难以维护。


解决方案:

1.最后,应该改为第二种方案,无论是走索引,还是sql复杂度,还是代码耦合性都远胜于第一种。
2.当然第二种就是会有非常多的冗余数据,当时就是产品也没有说限制查询的天数,担心表很容易就爆满,没有采用,其实这时候我们作为技术人员应该提出要限制查询的天数,而不是采用我之前用的方案,导致后患无穷。
3.写出来给大家一个参考避免走我的坑。
4.还有就是像这种报表的统计,尽量不要有逻辑删除的字段,如果有逻辑删除还要加上一个deleted=0,一般来说删除的数据都是少于不删除的,这时候索引就无效了,也会导致报表很慢,delete的数据尽量移除出统计表,用另外的表去存,而不是用统计的报表存。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值