栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

关于java报表的一些经验。

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

关于java报表的一些经验。

一、项目场景:

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


二、问题描述 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的数据尽量移除出统计表,用另外的表去存,而不是用统计的报表存。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/873778.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号