MyBatis 用 foreach 批量插入,6000 条数据花了 15 分钟,如何优化?
MyBatis 用 foreach 批量插入代码如下:
<insert id="batchInsert" parameterType="java.util.List">
insert into Test(id, username,password) values
<foreach collection="list" item="userList" index="index" separator=",">
(#{userList.id}, #{userList.username}, #{userList.password})
</foreach>
</insert>
使用以上代码实操结果:当一次性插入的列数达20+,行数达6000+时,整个插入的耗时花了15分钟。
原因:
默认执行器类型为Simple,会为每个语句创建一个新的预处理语句,即创建一个PreparedStatement对象;
MyBatis对于含有foreach的语句,无法采用缓存,那么在每次调用方法时,都会重新解析sql语句;
由于foreach后有6000+个values,PreparedStatement特别长,包含了很多占位符,对于占位符和参数的映射尤其耗时。
突破点:
在MySql Docs中提到,优化插入速度时,可以将多个小型操作组合到一个大型操作中;
在理想情况下,在单个连接中一次性发送多行的新数据,并将所有索引更新和一致性检查延迟到最后才进行;
当插入数量很多时,不能一次性全放在一条语句里。
解决办法:
1、如果非要用foreach的方式来插入,一次性插20~50行数比较合适。
2、MyBatis推荐的批量插入方式ExecutorType.BATCH (类似JDBC的ps.executeBatch() ),参考代码如下:
SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
SimpleTableMapper mapper = session.getMapper(SimpleTableMapper.class);
List<SimpleTableRecord> records = getRecordsToInsert();
BatchInsert<SimpleTableRecord> batchInsert = insert(records)
.into(simpleTable).map(id).toProperty("id")
.map(username).toProperty("username")
.map(password).toProperty("password")
.build().render(RenderingStrategy.MYBATIS3);
batchInsert.insertStatements().stream().forEach(mapper::insert);
session.commit();
}catch (Exception e) {
}finally {
session.close();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具