请教一个数据处理的需求,寻一个高效率的解决方法?

2023-03-28 11:00:39 +08:00
 godleon

前言

一个处理数据的需求,目前已经实现出来了,测试提出性能太低,所以请教一下,看看有没有比较好的处理实现方式,目前实现 sql 处理一部分,代码处理一部分
环境:Java1.8 Mysql 8

需求

type value date
1 10.111 2023-03-21 01:00:00
2 19.111 2023-03-21 01:00:00
2 11.111 2023-03-21 02:00:00
3 12.111 2023-03-21 02:00:00
1 13.111 2023-03-22 11:00:00
1 14.111 2023-03-22 12:00:00
1 15.111 2023-03-23 11:00:00

一张数据库表,如上, 用户根据某种类型添加数据,type 类型固定的 1-3,按日期插入数据,日期会重复因为是用户手动选择;
目标需求:按日期(yyyy-MM-dd)分组+倒序,每个类型查出最新的一条;并统计每个类型有多少条,
如上表数据,最终预期输出为:count(是这个日期分组下,这个类型的条数)

{
	"2023-03-21": [{
			"type": "1",
			"value": "10.111",
			"date": "2023-03-21 01:00:00",
                        "count": 1
		}, {
			"type": "2",
			"value": "11.111",
			"date": "2023-03-21 02:00:00",
                        "count": 2
		},
		{
			"type": "3",
			"value": "12.111",
			"date": "2023-03-21 02:00:00",
                        "count": 1
		}
	],
	"2023-03-22": [{
		"type": "1",
		"value": "14.111",
		"date": "2023-03-22 12:00:00",
                "count": 1
	}],
	"2023-03-23": [{
		"type": "1",
		"value": "15.111",
		"date": "2023-03-23 11:00:00",
                "count": 1
	}]
}

ps: 上述需求是接口里 1/5 的功能,还有后续处理
Ps: 代码简洁,支持使用第三方库

1738 次点击
所在节点    程序员
18 条回复
6a82aa9bfe
2023-03-28 11:10:00 +08:00
问问万能的 chatgpt?
dqzcwxb
2023-03-28 11:19:05 +08:00
你的需求是:将数据分组 count 且需要组名
实现方案有两个:
1,用 sql 分别实现分组统计,分组组名 性能优化点就是添加有效索引和并行查询;
2,用 sql 查询出所有数据然后用 Stream groupby 做分组统计,性能优化就是开启 parallelStream 和加机器配置;
godleon
2023-03-28 11:29:46 +08:00
@dqzcwxb 我现在就是 sql 分组,还遇到个问题就是分组的时候 再加 desc 分组就不会倒序了,然后又加子查询 用 max 取日期值找最新的,count 就得在分,因为我上面是 demo ,真实场景下我查出来的东西近 10W 条 40+个字段,我决定纯用代码处理试试
acctv2
2023-03-28 11:56:02 +08:00
explain 看看?
gjp0609
2023-03-28 12:25:46 +08:00
sql 开窗函数应该可以实现吧
liprais
2023-03-28 12:29:20 +08:00
mysql 8 直接 rank() over ( partition by )这种解决完事
Ikarosx
2023-03-28 14:09:12 +08:00
mark 一下,看看有没有更好的方式
```sql
SELECT DISTINCT
DATE_FORMAT( DATE, '%Y-%m-%d' ) day,
type,
COUNT(*) OVER ( PARTITION BY DATE_FORMAT( DATE, '%Y-%m-%d' ), type ) count,
FIRST_VALUE( DATE ) OVER ( PARTITION BY DATE_FORMAT( DATE, '%Y-%m-%d' ), type ORDER BY DATE DESC ) date,
FIRST_VALUE( VALUE ) OVER ( PARTITION BY DATE_FORMAT( DATE, '%Y-%m-%d' ), type ORDER BY DATE DESC ) value
FROM
test
```
wenxueywx
2023-03-28 17:08:54 +08:00
期望的数据有问题吧,3-22 的 type 为 1 的数据有两条。如果确认的话窗口函数确实可以解决
godleon
2023-03-28 17:56:10 +08:00
@wenxueywx 3-22 的 count 应该是 2, 写错了
Derek8863
2023-03-28 19:44:40 +08:00
建议用 ck 或者 presto 做计算引擎
dode
2023-03-28 20:33:44 +08:00
建议最新一条单独纯一个表🐇
dode
2023-03-28 20:34:53 +08:00
如果只有 3 种,就分别查询,再联合一下吧
crazyweeds
2023-03-28 21:14:05 +08:00
如果你返回条目数小的情况下,可以尝试代码层面多线程。SQL 拿到最新的日期列表,然后用日期作为参数,多线程循环执行 SQL 。
why1001
2023-03-28 21:23:56 +08:00
如果项目中引入了 guava 可以看下 Multimap 类型
noparking188
2023-03-28 21:44:08 +08:00
最好补充以下信息,决定方案选择
1. 数据更新频率;
2. 预估数据总量;
3. 数据查询频率;
4. 查询响应要求;

Java 后端里写业务逻辑对 MySQL 中的数据做复杂**分析**处理?也许提供业务场景上下文更清晰一点
14104chk
2023-03-28 23:14:22 +08:00
可以用一张统计表,修改的时候,把当前日期的统计数据更新
luzemin
2023-03-28 23:34:48 +08:00
同意楼上
要想让读路径短一些,那就让写路径长一些。
在写入的时候,把需要的结果单独更新到某个表 /位置。
wenxueywx
2023-03-29 11:29:30 +08:00
@godleon 特意用 mysql8.0 试了下纯 sql 的方法
CREATE TABLE `t01` (
`id` int NOT NULL AUTO_INCREMENT,
`type` int DEFAULT NULL,
`value` double DEFAULT NULL,
`date` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB ;

INSERT INTO `t01` VALUES (1,1,10.111,'2023-03-21 01:00:00'),(2,2,19.111,'2023-03-21 01:00:00'),(3,2,11.111,'2023-03-21 02:00:00'),(4,3,12.111,'2023-03-21 02:00:00'),(5,1,13.111,'2023-03-22 11:00:00'),(6,1,14.111,'2023-03-22 12:00:00'),(7,1,15.111,'2023-03-23 12:00:00');

select distinct date(`date`) as`date`,`type`,count(*) over(partition by date(`date`),`type`) as count, first_value(`date`) over (partition by date(`date`),`type` order by `date` desc) as `latest_datetime`,first_value(`value`) over (partition by date(`date`),`type` order by `date` desc) as `latest_value` from t01;
+------------+------+-------+---------------------+--------------+
| date | type | count | latest_datetime | latest_value |
+------------+------+-------+---------------------+--------------+
| 2023-03-21 | 1 | 1 | 2023-03-21 01:00:00 | 10.111 |
| 2023-03-21 | 2 | 2 | 2023-03-21 02:00:00 | 11.111 |
| 2023-03-21 | 3 | 1 | 2023-03-21 02:00:00 | 12.111 |
| 2023-03-22 | 1 | 2 | 2023-03-22 12:00:00 | 14.111 |
| 2023-03-23 | 1 | 1 | 2023-03-23 12:00:00 | 15.111 |
+------------+------+-------+---------------------+--------------+

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/927776

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX