一个列表优化五版还是差怎么办 只能重构啊~~

一、背景:

当前业务中有一个列表及时性要求很高,前端会五秒定时请求一次列表,由于之前数据库设计的原因,导致查询语句复杂且难以优化(优化好几版之后发现性能还是不达标),痛定思痛决定重构他。

二、重构原因:

1、即使事件列表查询慢。

2、即时事件列表查询会导致OOM。

三、详细描述:

1、查询列表慢:

该查询需要的查询条件散落在各个表中,需要作为条件的除业务事件表的字段外,需要关联查询子事件的device_id,媒体文件的file_sort,最后导致查询语句复杂。

解决方案:
重构存储模型,将需要用到的条件重新规整。
优化后,会将媒体文件hash_name冗余到业务表中,根据入表规则来修改该字段;将子事件的device_id字段,单独抽出来一个业务事件和device_id的关系表,用来查询。
在这里插入图片描述
备注:红色标识为需要关联字段,紫色标识为需要查询字段。
在这里插入图片描述

备注:红色标识为需要关联字段,紫色标识为需要查询字段,蓝色标识为媒体文件冗余到业务事件表的字段。

业务事件关系表结构:
在这里插入图片描述

V3.9.1 查询即时页面列表sql:



SELECT
	DISTINCT
	be.business_event_uuid business_event_uuid,
	be.start_time,
	be.end_time,
	be.business_event_type business_event_type,
	be.business_object_types business_object_types,
	be.business_event_status business_event_status,
	be.remark,
	ce.business_event_uuid,
	ce.uuid child_event_uuid,
	ce.occur_time,
	ce.event_type child_event_type,
	ce.device_id,
	JSON_UNQUOTE(
	json_extract( ce.expand_field, '$.deviceName' )) device_name,
	ce.event_status child_event_status,
	cemf.hash_name 
FROM
	(
	SELECT
		uuid business_event_uuid,
		start_time,
		end_time,
		event_type business_event_type,
		object_types business_object_types,
		event_status business_event_status,
		remark 
	FROM
		business_event 
	WHERE
		uuid IN (
		SELECT
			t1.business_event_uuid 
		FROM
			(
			SELECT
				business_event_uuid,
				max( occur_time ) occur_time 
			FROM
				child_event 
			WHERE
        occur_time > "2021-12-05 11:21:03" 
				and event_status != 'ignore' 
				and device_id in ("4401000000288")
			GROUP BY
				business_event_uuid 
			) t1 
		) 
		AND region_id = "637506f6e63a401fbe3de34cda51a35a" 
		AND event_status IN ( "untreated" ) 
	ORDER BY
		end_time DESC 
    LIMIT 0,30 
	) be
	INNER JOIN child_event ce ON ce.business_event_uuid = be.business_event_uuid
	LEFT JOIN child_event_media_file cemf ON cemf.child_event_uuid = ce.uuid 
	AND cemf.file_sort = '0' 
ORDER BY
	ce.occur_time DESC

事件的缩略图会加到业务事件表中,业务关系表适用的场景是一个业务事件对应多个点位时为一对多,现在业务为一对一,数据量不会太大。

V3.9.2



SELECT
	t1.uuid,
	t1.start_time,
	t1.end_time,
	t1.event_type,
	t1.object_types,
	t1.event_status,
	t1.remark,
	t2.device_id,
	t1.hash_name 
FROM
	business_event t1
	LEFT JOIN business_child_media t2 ON t1.uuid = t2.business_event_uuid 
WHERE
	 region_id = "637506f6e63a401fbe3de34cda51a35a" 
	AND t1.end_time > "2021-12-05 11:21:03" 
	AND event_status IN ( "untreated" ) 
	AND	 t2.device_id IN ("4401000000295")
	ORDER BY end_time desc

2、查询列表语句会导致OOM:

查询语句中会有查询某些点位所有的事件uuid,这个sql会非常大,一直查询会导致druid的内存占用越来越高,导致后端一直FGC,最终导致OOM。
V3.9.1中查询Uuid时加了时间过滤条件。
备注:需要查询uuid的原因是查询需要点位id的过滤条件,而这个数据只在子事件表中存在。

V3.9.2中重构,会将device_id字段抽出来,与business_uuid单独成为一个关系表,用来查询。

3、三表联查查询的数据用到的有限,可以通过和前端交互修改接口,将查询复杂度降级。

具体表现:
1> 查询所有子事件所对应的媒体文件中的hash_name,但只在前端页面用到了一个hash_name。

解决方案:
hash_name冗余到业务表中,入库新增校验逻辑更新业务事件表中该字段。

2> 查询所有子事件的数据,但只有鼠标悬浮到子事件上才会展现所有子事件,该行为为小概率事件。
解决方案:
将查询所有子事件数据新加一个接口返回,原查询列表去除所有子事件,并且添加子事件的缩略图到业务事件中。

四、优化方案总结:

1、重构存储模型,将需要用到的条件重新规整,新增关系表。
2、根据业务需求优化与前端交互,减少性能损耗。

五、需代码兼容:

1、媒体文件入库时,需考虑缩略图入业务事件表。
2、业务事件关系表定时清除。
3、数据迁移。

六、性能对比测试文档:

开发的压测文档能有多小心谨慎~


												————  What is worth doing is worth doing well.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值