生产慎用之调试日志对空间矢量数据批量插入的性能影响-以MybatisPlus为例
目录
前言
在现代软件开发中,性能优化是一个永恒的话题,尤其是在处理大规模数据时,如何提升数据库操作的效率成为了一个关键问题。在数据库操作中,批量插入空间矢量数据是一个常见的需求,尤其是在地理信息系统(GIS)和空间数据分析领域。调试日志是软件开发中不可或缺的工具,它帮助开发者追踪程序的运行状态,定位问题和异常。然而,日志记录本身是一个资源密集型的操作,尤其是在生产环境中,过多的日志记录可能会对性能产生负面影响。对于空间矢量数据的批量插入操作,这种影响尤为明显,因为这类操作通常涉及大量的I/O操作和数据库交互。
尽管调试日志对于开发和问题排查至关重要,但在生产环境中,它们可能会成为性能瓶颈。每次日志记录都会涉及到I/O操作,这会占用CPU时间和磁盘I/O资源。在批量插入空间矢量数据时,如果日志记录过于频繁,可能会导致以下问题:
- 降低I/O效率:日志记录会占用磁盘I/O资源,这可能会与数据库操作竞争资源,导致整体性能下降。
- 增加延迟:日志记录可能会引入额外的延迟,尤其是在高并发情况下,这会直接影响到批量插入操作的响应时间。
- 资源竞争:日志记录和数据库操作可能会竞争有限的系统资源,如CPU和内存,这可能会导致性能瓶颈。
调试日志是一把双刃剑,它在帮助开发者解决问题的同时,也可能对生产环境的性能产生影响。在处理空间矢量数据的批量插入时,合理控制和优化日志记录是提升性能的关键。本文通过在MybatisPlus中调整插入SQL的输出对比前后的耗时与内存的占用,最大限度地减少对性能的负面影响。本文将深入探讨这些策略的具体实现和最佳实践,以期为Java开发者提供实用的指导和建议。
一、一些缘由
其实在日常工作当中,空间矢量数据的数据量都是非常大。不仅是范围大,属性数据也尤其多,不仅属性列多,而且数据行数也可能非常多。那么我们在使用ORM框架在操作这些数据的时候,在进行空间数据入库的时候尤其需要注意性能的影响。有一些程序需要追求高性能,尤其是一些需要快速计算的场景,用户需要尽快的将数据入库,好开展后续的业务。
之前有一个朋友给发了私信,说他们在处理线上的生产数据时,数据的规模大约是几十W的规模。在使用GeoTools读取Shapefile后,然后调用Mybatis-Plus来进行数据入库。它的整体性能不高,耗时比较久,然后就找到博主聊了一下。原始聊天截图就不放出来了。分享其中遇到的一些问题:
1、这位朋友在进行批量数据入库的时候,使用循环来进行调用,没有使用批量操作。
2、系统的日志级别开的比较低,为了方便监控程序,系统的日志级别在生产环境上也是Debug。
3、服务器在空间数据库入库时,内存占用较高。
1、性能分析
在了解了一些程序的执行细节之后,我也做了一个对照实验。实验的主要目的是对比应用程序中调试日志的输出对性能影响 ,主要方法就是在程序执行时打开和关闭系统日志,通过观察打开前后的应用程序执行消耗时间和使用Java VisualVM监控的CPU和内存消耗情况来对比。
二、插入方式调整
为了首先将应用程序的插入调整到一个比较好的执行状态,我们先把原来的循环插入的方式进行了修改,改成批量插入的形式。因此这里有必要对批量插入的具体实现进行一个简单的介绍。
1、批量插入的实现
在我们的代码中,使用的ORM框架是Mybatis-Plus,熟悉这个框架的小伙伴们一定知道。在MP中除了有单个插入的方法,还提供了一个批量插入的实现。因此,如果您是使用了MP这种的增强框架,那么改造起来还是比较快的,否则就需要大家自己去实现批量插入的方法。在MP中需要调用service提供的saveBatch(List,Size)即可。在在我的示例代码中,实现批量插入的关键代码如下所示:
2、MP的批量插入实现
上一节中对Mp的批量插入的方法进行了调用,这里我们依然对saveBatch方法进行简单的介绍,好让大家对saveBatch有一个直观的印象。我们可以打开ServiceImpl的实现类中的以下代码:
这里的方法表示首先获取sql的Statement对象,然后调用批量执行的方法。被调用的方法如下:
来看一下insert方法的处理逻辑,最终的执行update的方法如下:
当然大家在使用这个类的时候还是非常方便的,只要调用相应的方法即可实现分批导入。
3、日志的配置
在实例的应用开发过程中,日志的输出与管理,我们使用Logback组件。在最开始的时候,在对比实验中,首先我们采用默认的方式,即对应的ORM处理组件中的日志级别使用默认方法。具体如何在Logback中进行日志的设置,请大家结合互联网相关资料进行查询,这些都是比较成熟的。
三、默认处理方式
对比实验的第一种实现方法就是采用默认的方法,即使用默认的日志级别。但是在最开始时,我们还是给出测试的代码的全部。如果您也感兴趣,可以替换相应的文件来进行验证这个过程。测试结果可能随着数据量的不同,数据属性字段的不同而有所不同。
1、基础程序代码
为了还原网友提出的问题,也能尽快的找到原因。我们这里就以之前的全球主要城市为例,重点讲解如何进行数据的处理和融合,以及最终如何进入到数据库中。实例代码如下:
在不关闭执行SQL日志的情况,我们来看一下它的相关性能指标。
2、执行情况
在默认情况下,这段程序在执行过程中会输出大量的调试日志,如下图所示:
在我们的控制台中有许多的插入日志,同时可以看到,整个空间数据入库的时间为29512毫秒,即将近30秒。除了时间的消耗,我们再来看一内存方面的消耗。
可以很直观的看到,在进行大量的日志输出时,内存的使用量还是比较大,同时根据不同的批次呈现一个比较有规律的上升和下降,而最大的内存使用接近1000MB左右。 接下来,我们再来看一下关闭日志输出后的效果。
四、提升调试日志等级
为了实现在运行时将这个插入SQL的日式调试等级,我们在Logback中进行相应的配置。以此来验证在提升SQL调试日志的等级后,这个批量插入的方法是不是有一个性能的提升。
1、在logback中进行设置
在系统中,我们采用logback来进行日志的配置,因此我们首先需要在logback中进行相应的设置。将日志的级别从debug提升到error,只有在发生错误的时候才进行输出。设置的关键代码如下所示:
请注意,这里的com.yelang.project.extend.earthquake.mapper.Ne10mPopulatedPlacesMapper标识我们需要关闭的ORM类的全名。我们将他的日志级别提升到了error。
2、提升后的效果
在将输出日志关闭之后,在控制台中首先就没有了sql的调试日志,说明配置成功。
可以看到控制台很干净,调试的SQL日志已经被清理掉。同时注意耗时情况,变成了7046,也就是7秒的时间就完成了处理。在来后台看一下是不是真的处理成功。在数据库进行相应的数据查询。
可以看到,数据的总条数也是7342条。因此可以判断,关闭sql调试日志后,对时间的消耗降低了很多,从30秒优化到了7秒, 大概提升76%;再来看一下内存的占用情况。
相对于默认的处理情况而言,提升了日志等级的处理方式,其内存占用更加平稳,波动小。同时最大的内存占用在700MB左右,更多是500MB以下。从侧面也说明了优化的效果。
五、总结
以上就是本文的主要内容,本文通过在MybatisPlus中调整插入SQL的输出对比前后的耗时与内存的占用,最大限度地减少对性能的负面影响。文章通过对照实验,对比了开启调试日志和关闭调试日志后的数据插入性能,从对比实验结果可以看到。关闭调试日志后,我们的应用程序耗时更短,同时内存的占用也更低。如果在生产环境中进行使用,尤其是新手同志,为了观察参数就留下了很多调试信息,这样反而加大了系统的负担。所以要请大家一定综合理性的评估,关闭不必要的调试日志,让应用程序的性能最大。行文仓库,定有许多不足之处,如有不足,在此恳请各位专家在评论区批评指出,不胜感激。
- 点赞
- 收藏
- 关注作者
评论(0)