数据导入性能优化小记

1.背景

所在的活动组经常需要导入券码,然后发放券码。这次导入了100w券码,但是非常耗时,需要1个小时。如果有上千万的券,那么时间非常久,需要达到10多个小时,基于这个点排查原因,提升导入速度。

2.发现

2.1.线上反馈导入100w需要1小时

2.2.查看导入部分的关键代码

image.png

上面的代码的背景是每一行导入数据就会调用一次,然后通过isOnePage判断,如果达到一页了就会批量保存到数据库里面。

2.3.查看生产日志

发现生产的云日志【导入完成一批次】的日志打印间隔都需要2s,我这里一页的大小是1000条,所以就得定位为什么1000条需要2s这么久,那么第一反应就是数据库插入慢了

2.4.sql插入性能

通过arthas分别trace了couponCodeManager.saveListWithIgnorethis.updateById(finalEntity)以及stockManager.updateBySkuId(product.getSkuId(), (long) successNum, true, "券码导入"),发现这些数据库的操作都很快,也就几十ms,所以数据库的插入没啥问题。

2.5.查看线上调用情况

image.png

通过arthas的trace,这里看到了一些奇怪的地方,这个代码每次走这个代理需要2ms多,第一次看到2ms觉得没啥,时间也不长,但是仔细一想,这个函数是一条数据就会调用一次,那么1000条就是2ms * 2000=2s,所以问题就找到了。也就是这个每次循环跑的代理太耗时,到这里大致就能猜到原因了,这个方法代理的有@Transactional

2.6.原因

在方法上的@Transactional导致每次的循环就会和数据库交互,开事务,提交事务。
1000次的循环就执行1000次的数据库交互。性能自然慢了。

解决

针对上面的问题,解决也很简单,就是只有到一页了以后再去和数据库交互,处理数据。不要直接在方法上打@Transactional注解

image.png

3.结果

从之前100w导入1小时提升到了3分钟。
对于@Transactional的使用以后还是要更加谨慎一些,需要改变以后那种只需要事务就往方法打这个注解的惯性思维。
很多时候一个方法上面可能有rpc等各种和当前事务无关的耗时操作,这样还把事务注解打上面,非常影响性能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容