记录一个MyBatis缓存与事务引起的性能bug

问题发现

最近在做的项目中,有一个功能模块涉及比较大数据量的查询和导出,分别是IMSI数据和MAC数据。刚开始这部分功能使用了级联查询,查询字段、查询条件使用函数(如在查询条件为时间戳,进行格式化为年与日)等操作,但是随着数据量加大查询效率大幅度降低;所以后来对那部分的功能进行了一些优化,如取消连接查询,取消函数的使用,转而在业务逻辑中对关联表字段和时间进行设置和格式化。
而且导出也使用了EasyExcel进行导出,效率已经很高了。
但是上周前端要求导出功能响应时间要在1分钟之内,于是经过协商,我们决定对导出数据进行最大记录限制,在实验了几次之后最后我将最大记录数控制在60W。
但是昨天前端再次找到我,说IMSI没有问题,但是MAC的导出超出了响应时间。

排查过程

于是我在本地进行两个接口的响应时间测试,发现同样的数据量,MAC比IMSI的导出速度满了不止一点半点,可是其实MAC的查询逻辑比IMSI还要简单,实在想不明白,于是我开始逐行进行响应时间测试。
一开始我以为是查询效率的问题,但是经过直接执行SQL和在业务中打断点测试SQL查询时间,都很正常。
后来我开始测试前面说的,在业务中对关联字段和时间设置的逻辑。果不其然,IMSI处理部分,即使是60W,甚至100W条,也能在几秒内处理完成;而MAC部分,即使只有10W也半天处理不完。
于是我开始在循环中打印对象,打印每一行处理之后的时间。明显看得出MAC的打印过程十分的慢。每个循环中有两行操作,一行是将毫秒值转为Date,一行是通过设备ID查询数据库获取设备名称。我在每一行后面都将当前时间进行打印。说实话也是死马当活马医,万一看出问题了呢?
大概像这样

	//处理查询逻辑略……
	//执行查询
	List<MacVO> list = macDataMapper.queryMacInfo(macSearch);
	//设置属性
	System.out.println("遍历开始");
	list.forEach(macVO -> {
	    macVO.setAcquisitionTime(new Date(macVO.getReportTime()));
	    System.out.println("采集时间设置成功"+System.currentTimeMillis());
	    macVO.setDeviceName(imsiSourceDataMapper.getEquipmentNameById(macVO.getDeviceNo()));
	    System.out.println("设备名称设置成功"+System.currentTimeMillis());
	    System.out.println(macVO);
	});

同时IMSI也进行同样的处理,先查他个100条,看一下打印的时间,道理是哪里有问题

没想到果然被我发现了问题!两边打印出来的日志是这样的,左边是IMSI,右边是MAC
在这里插入图片描述
可以看到,每次查询数据库获取设备名称大概需要50毫秒左右的时间,而IMSI每次刚开始查询时确实每次都会查询,但是后面再遇到重复的设备时就不再查询了,而是直接迅速获取到结果;而MAC那边则每一次都会执行一次查询!
所以,其实是MyBatis的缓存机制的问题!一边使用了缓存机制而另外一边没有!

知识补充

以下内容来源于网络资料(这篇博客:MyBatis 一级缓存、二级缓存全详解(一)

MyBatis 中的缓存就是说 MyBatis 在执行一次SQL查询或者SQL更新之后,这条SQL语句并不会消失,而是被MyBatis 缓存起来,当再次执行相同SQL语句的时候,就会直接从缓存中进行提取,而不是再次执行SQL命令。
MyBatis中的缓存分为一级缓存和二级缓存,一级缓存又被称为 SqlSession 级别的缓存,二级缓存又被称为表级缓存。
一级缓存是 SqlSession级别 的缓存。在操作数据库时需要构造 sqlSession 对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的 sqlSession 之间的缓存数据区域(HashMap)是互相不影响的。用一张图来表示一下一级缓存,其中每一个 SqlSession 的内部都会有一个一级缓存对象。
MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能。

解决方式

那么,为什么同样的项目里面,两边一个启用了缓存一个没启用呢!
因为,缓存是基于事务的呀!!!
所以,解决办法就是在MAC查询那边添加事务就好了呀!
@Transactional(rollbackFor = Exception.class)
至此,问题解决,两边查询一样嗖嗖快!

总结

这真是个大坑,一个注解解决的问题我排查了好久才排查出来……不过也顺便详细了解了一下MyBatis的事务和缓存机制,是个不错的经历!以及,要合理利用事务呀!MAC那边是之前同事做的我接手的,我也妹想到他没用事务!挖坑!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值