MyBatis批量插入的3种方案对比,速度差10倍!

boyanx3个月前技术教程21

你还在用for循环做MyBatis批量插入? 本文通过真实案例+代码实测,对比三种批量插入方案的速度差异与实现原理。文末附实测数据截图,看完立省80%数据库操作时间!


一、青铜方案:循环单条插入(性能灾难)

// 典型错误示例
for (User user : userList) {
    userMapper.insert(user);
}

特点

  • 每条insert语句单独执行
  • 每次请求都经历完整JDBC流程
  • 事务自动提交(除非手动控制)

实测结果(1万条数据):

  • 耗时:约30秒
  • 优点:代码简单
  • 缺点:产生1万次网络IO,99%的时间浪费在连接开销

二、白银方案:BatchExecutor批处理(性能提升10倍)

// 开启批处理模式
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

for (User user : userList) {
    mapper.insert(user);
    if(i % 1000 == 0){
        sqlSession.flushStatements(); // 分段提交
    }
}
sqlSession.commit();

核心原理

  • 通过ExecutorType.BATCH启用JDBC批处理
  • 将多个SQL语句打包发送
  • 事务统一提交

实测结果(1万条数据):

  • 耗时:约3秒
  • 优点:JDBC层优化,网络IO减少90%
  • 缺点:需要手动控制提交时机

三、王者方案:动态SQL拼接(极限性能)

<!-- XML动态SQL -->
<insert id="batchInsert">
    INSERT INTO user (name,age) VALUES
    <foreach collection="list" item="item" separator=",">
        (#{item.name}, #{item.age})
    </foreach>
</insert>

执行特点

  • 生成单条INSERT INTO ... VALUES (...),(...)语句
  • 数据库单次解析执行
  • 利用数据库批量写入优化

实测结果(1万条数据):

  • 耗时:约1秒
  • 优点:理论最快执行方式
  • 致命缺陷:SQL长度限制(MySQL默认4MB)

全方位对比表

维度

循环单条插入

BatchExecutor

动态SQL拼接

执行方式

N条独立SQL

JDBC批处理

单条大SQL

网络IO次数

N次

1次

1次

事务控制

自动提交

手动提交

单事务

内存消耗

高(SQL缓存)

可读性

★★★★

★★★

★★

适用场景

<100条

1k-10w级

<5k条(防溢出)


实测数据验证(1万条记录)


避坑指南

  1. 动态SQL长度陷阱:MySQL的max_allowed_packet参数限制单条SQL大小
  2. 批处理内存溢出:每5千条左右建议执行flushStatements()
  3. 事务一致性:BatchExecutor必须显式commit才会生效
  4. 主键回写:动态SQL方案无法获取全部自增ID

选型建议

  • 小数据量(<500条):动态SQL方案最优
  • 常规批量(1k-5w条):BatchExecutor最稳妥
  • 超大数据量(>10w条):结合BatchExecutor+分段提交

终极技巧:生产环境推荐组合方案:BatchExecutor + 分批次提交 + 动态SQL长度控制,实测可提升百倍性能!


思考题:为什么动态SQL方案在Oracle数据库中反而可能变慢?欢迎评论区讨论!(提示:与SQL解析机制有关)

相关文章

别让这5个编程习惯毁了你的代码!AI检测工具帮你一键修复

——从“代码草莽”到“AI护法”的升级指南01 硬编码常量:埋下“隐形地雷”坏习惯表现:直接在代码中写入“魔改版”参数(如if (status == 999)),导致后期维护时“代码即天书”。AI修复...

Java同步代码块与同步方法的那些事儿

Java同步代码块与同步方法的那些事儿同步代码块:锁住指定区域想象一下,你正在参加一场紧张的拍卖会,拍卖师手里拿着珍贵的拍品。如果多个竞拍者都想抢着喊价,场面就会变得混乱不堪。这时拍卖师会设置一些规则...

不会Python?1个视频教会你!#Python教程#大学生必看

Python零基础速通指南一、精选视频教程推荐(附学习路线)3小时语法速通核心章节:变量定义、条件判断、循环结构、函数封装(参考网易公开课《1-1.认识python》到《1-12.顺序选择循环》章节)...

在 MySQL 中使用 TINYINT 类型进行比较查询时,需要注意的事项

最近在项目中在表中新增了两个字段,使用的TINYINT(1)定义布尔类型,并且未设置默认值,这个字段是后来新增,新增之后没有对以前的历史数据进行处理,于是在代码中比较的时候,使用了如下示例代码:Lis...

Java隐藏的10倍效率技巧!90%程序员不知道的魔法方法(附代码)

导语:“同事1小时写完的代码,你用了1天?不是技术差距,是你不懂Java的隐藏魔法!今日头条首发7个颠覆认知的编码技巧,文末送《Java性能优化秘籍》!”一、灵魂暴击:用对工具代码量少一半问题场景:“...

python编程错误“大侦探”:如何精准揪出代码中的小调皮

在编程的奇妙世界里,我们就像勇敢的探险家,有时也会遇到一些“小调皮”——编程错误。这些错误就像是隐藏在代码森林中的神秘陷阱,让我们一不小心就栽了跟头。那么,如何才能像聪明的侦探一样,精准地揪出这些错误...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。