1、现状
目前系统中当一次持久化多条明细数据时采用简单粗暴for循环的方式。这种方式的优点是实现简单,数据量不多的情况下不存在什么问题,但是当数据量变大相应带来的问题也很明显,就是接口耗时严重并且接口耗时与数据量有直接关系,同时由于我们通常在批量执行数据持久化时都是带有事务操作,这就会导致数据库连接长时间不释放。等等问题见下图。
图中每一个高点都是由于多条明细批量持久化时造成的耗时。
2、解决方案
基于这个问题,目前提供的批量数据持久化解决方案有两种:
(1)、采用mybatis的foreach的方式批量持久化数据。
这种方式优点是能够集中将多条数据集成拼接成一条SQL执行。但是缺点是当数据量较大时,会造成SQL拼接过大,非常大的字符串会直接晋升到老年代中直到FullGC才会被释放,出现这种场景一般需要将数据分片,将逻辑复杂化,因此本次不采用这种方式。
(2)、采用指定mybatis的ExecutorType的模式为batch方式。
在默认情况下mybatis的Executor组件的模式为Simple模式,需要我们显示的在配置文件中指定需要的模式。
这种方式的优点主要是依赖JDBC的Statement提供的批处理能力,能够将批量SQL一次提交给Server大大提升执行效率,减少每次执行SQL时不必要的网络IO等。
另外client端的URL中需要指定rewriteBatchedStatements参数显示开启batch模式。
3、效果对比
以下是对比Simple模式和Batch模式for循环200次的基准测试平均耗时。
batch模式耗时0.5秒
simple模式耗时13.5秒
把for循环次数增加到1000次的时候基准测试平均耗时。
batch模式耗时0.5秒
simple模式耗时61.5秒
4、实现方案
采用AOP的方式显示将SQLSession的ExecutorType设置为Batch。在需要执行批量操作时,通过注解标记的方式实现批量操作。
具体方案可以做成插件的方式。具体实现方案需要完善。
存在的问题
batch模式下,批量更新的返回值不会返回。