Mybatis批量插入大数据导致堆内存溢出问题解决方案

原文源自:https://my.oschina.net/u/2428301/blog/1796597

Exception in thread "Thread-8" java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Arrays.java:3332)
	at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:137)
	at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:121)
	at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:421)
	at java.lang.StringBuilder.append(StringBuilder.java:136)
	at org.apache.ibatis.scripting.xmltags.DynamicContext.appendSql(DynamicContext.java:65)
	at org.apache.ibatis.scripting.xmltags.ForEachSqlNode$PrefixedContext.appendSql(ForEachSqlNode.java:208)
	at org.apache.ibatis.scripting.xmltags.ForEachSqlNode$FilteredDynamicContext.appendSql(ForEachSqlNode.java:165)
	at org.apache.ibatis.scripting.xmltags.StaticTextSqlNode.apply(StaticTextSqlNode.java:30)
	at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33)
	at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:35)
	at org.apache.ibatis.scripting.xmltags.ChooseSqlNode.apply(ChooseSqlNode.java:35)
	at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33)
	at org.apache.ibatis.scripting.xmltags.ForEachSqlNode.apply(ForEachSqlNode.java:82)
	at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33)
	at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:41)
	at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:292)
	at org.apache.ibatis.executor.statement.BaseStatementHandler.<init>(BaseStatementHandler.java:64)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.<init>(PreparedStatementHandler.java:40)
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.<init>(RoutingStatementHandler.java:46)
	at org.apache.ibatis.session.Configuration.newStatementHandler(Configuration.java:523)
	at org.apache.ibatis.executor.ReuseExecutor.doUpdate(ReuseExecutor.java:50)
	at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
	at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
	at sun.reflect.GeneratedMethodAccessor89.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:63)
	at com.sun.proxy.$Proxy25.update(Unknown Source)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185)
	at sun.reflect.GeneratedMethodAccessor90.invoke(Unknown Source)

JVM环境:-Xms64m -Xmx128m

        由于①mybatis的DAO接口我是传List,而mybatis的foreach底层代码是arrays的,②所以需要把List转arrays,然后遍历Arrays,③用StringBuilder拼接SQL的。

        问题出现在②③步!因生成的arrays对象和StringBuilder对象是在堆内存中的,而堆内存的对象GC回收机制是:只有JVM的使用内存达到最大内存时的一定阀值,才会执行GC回收!

        如果当本身JVM已经使用了占有了JVM的最大内存的90%,那么②③步的生成的对象占有内存+本身已占有的内存如果超出JVM的最大内存,而JVM又来不及执行GC时就会导致JVM内存溢出,当前线程挂掉!

       我的解决方法是:实行多段相继执行,每次只批量执行3000个对象,从而保证Arrays和StringBuilder过大,当然3000个是相对于我的JVM环境而言,每个人也可以根据自身的JVM环境进行调优。上文观点是个人的理解,如果有什么不对的地方请指出,谢谢。 

public int batchSave(String stockCode, String stockType, String tableNum, List<StockMarket> stockMarkets) throws Exception {
		int size = stockMarkets.size();
		int index = 0;
		while(true) {
			if(index+3000>=size) {
				this.batchSave(stockType, tableNum, stockMarkets.subList(index, size-1));
				break;
			}else {
				this.batchSave(stockType, tableNum, stockMarkets.subList(index, index+3000));
				index = index+3000;
			}
			
		}
		return size;
	}

参考:

mybaits批量插入引起的血案:https://blog.csdn.net/syy_c_j/article/details/52151402

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在使用MyBatis-Plus进行大数据插入时,可以通过使用批量插入的方式提高性能。引用中的代码示例展示了如何使用批量插入。首先,创建一个实体列表(例如List<CmpWork> entityList),将要插入的数据添加到列表中。然后,调用对应的service方法(例如workIService.insertBatch(entityList))来执行批量插入操作。 批量插入的优势在于,相较于单条插入,它可以大大减少与数据库的交互次数,从而提高插入的效率。在较小规模的数据(如1000条数据)情况下,可能并没有显著的性能差异。但在大数据环境下,批量操作的优势会更加明显,因为它可以减少数据库操作的开销和网络传输的时间。 总结起来,使用MyBatis-Plus进行大数据插入时,批量插入是一种提高性能的方式。在实际应用中,可以根据具体情况选择适合的插入方式,平衡插入的效率和资源的消耗。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [MyBatis-Plus 的官方示例(mybatis-plus-samples-master.zip)](https://download.csdn.net/download/weixin_43800734/85290560)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [MyBatis-Plus 批量插入数据](https://blog.csdn.net/weixin_57763462/article/details/119416692)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值