MyBatisPlus批量插入性能优化实战
1. 为什么需要自己实现MyBatisPlus批量插入MyBatisPlus作为MyBatis的增强工具虽然提供了很多便捷的CRUD操作但在批量插入方面确实存在一些局限性。官方提供的saveBatch方法在实际使用中会遇到几个典型问题性能瓶颈默认的saveBatch实际上是循环执行单条INSERT语句当数据量达到500条以上时性能下降明显事务管理原生批量插入在事务失败时缺乏细粒度的控制能力特殊需求无法支持INSERT IGNORE、ON DUPLICATE KEY UPDATE等特殊语法我在电商系统开发中就遇到过这样的场景需要一次性导入3000商品SKU数据使用默认的saveBatch方法耗时超过30秒而改造后的批量插入方案仅需3秒左右。2. 批量插入的三种实现方案对比2.1 原生JDBC批量操作Connection connection dataSource.getConnection(); connection.setAutoCommit(false); PreparedStatement ps connection.prepareStatement(INSERT INTO user(name,age) VALUES(?,?)); for (User user : userList) { ps.setString(1, user.getName()); ps.setInt(2, user.getAge()); ps.addBatch(); } ps.executeBatch(); connection.commit();优点执行效率最高内存占用可控缺点需要手动管理连接和事务代码较为原始2.2 MyBatis的foreach动态SQLinsert idbatchInsert INSERT INTO user(name, age) VALUES foreach collectionlist itemitem separator, (#{item.name}, #{item.age}) /foreach /insert优点与MyBatis生态无缝集成支持MyBatis的所有特性缺点超长SQL可能被数据库拒绝参数过多时性能下降2.3 改造MyBatisPlus的saveBatch这是我们重点要实现的方案它能在保持MyBatisPlus使用习惯的同时获得更好的性能。3. 深度改造saveBatch方法3.1 基础实现原理我们需要继承DefaultSqlInjector并重写inspectInject方法public class CustomSqlInjector extends DefaultSqlInjector { Override public ListAbstractMethod getMethodList(Class? mapperClass) { ListAbstractMethod methodList super.getMethodList(mapperClass); methodList.add(new InsertBatchSomeColumn()); return methodList; } }关键点在于InsertBatchSomeColumn这个自定义方法类public class InsertBatchSomeColumn extends AbstractMethod { Override public MappedStatement injectMappedStatement(...) { String sql scriptINSERT INTO %s %s VALUES %s/script; SqlSource sqlSource languageDriver.createSqlSource(...); return this.addInsertMappedStatement(mapperClass, modelClass, insertBatchSomeColumn, sqlSource); } }3.2 性能优化技巧分批处理即使使用批量插入单次也不宜超过1000条public static T boolean saveBatch(CollectionT entityList, int batchSize) { ListT batchList new ArrayList(); for (T entity : entityList) { batchList.add(entity); if (batchList.size() batchSize) { baseMapper.insertBatchSomeColumn(batchList); batchList.clear(); } } if (!batchList.isEmpty()) { baseMapper.insertBatchSomeColumn(batchList); } return true; }字段过滤只插入必要的字段TableField(insertStrategy FieldStrategy.NOT_EMPTY) private String name;连接池配置适当增大连接池的maxWait和maxActive参数3.3 事务增强实现建议结合Spring的Transactional注解实现更灵活的事务控制Transactional(rollbackFor Exception.class) public void batchInsertWithTransaction(ListUser users) { // 分批插入逻辑 int batchSize 500; for (int i 0; i users.size(); i batchSize) { ListUser batchList users.subList(i, Math.min(i batchSize, users.size())); userMapper.insertBatchSomeColumn(batchList); // 业务逻辑处理 processBatch(batchList); } }4. 实战中的坑与解决方案4.1 主键冲突问题现象批量插入时遇到主键冲突导致整个批次失败解决方案使用INSERT IGNORE语法MySQLInsert(scriptINSERT IGNORE INTO user(name,age) VALUES foreach collectionlist itemitem separator, (#{item.name},#{item.age})/foreach/script) void insertBatchIgnore(ListUser users);使用ON DUPLICATE KEY UPDATEInsert(scriptINSERT INTO user(name,age) VALUES foreach collectionlist itemitem separator, (#{item.name},#{item.age})/foreach ON DUPLICATE KEY UPDATE ageVALUES(age)/script) void insertBatchOrUpdate(ListUser users);4.2 大数据量内存溢出现象导入10万条数据时出现OOM解决方案使用流式处理try (BufferedReader reader new BufferedReader(new FileReader(file))) { String line; ListUser batch new ArrayList(1000); while ((line reader.readLine()) ! null) { User user parseLine(line); batch.add(user); if (batch.size() 1000) { userMapper.insertBatchSomeColumn(batch); batch.clear(); } } if (!batch.isEmpty()) { userMapper.insertBatchSomeColumn(batch); } }调整JVM参数-XX:UseG1GC -Xmx2g4.3 字段类型不匹配现象枚举类型字段插入失败解决方案实现自定义TypeHandlerMappedTypes(UserType.class) public class UserTypeHandler extends BaseTypeHandlerUserType { Override public void setNonNullParameter(PreparedStatement ps, int i, UserType parameter, JdbcType jdbcType) { ps.setInt(i, parameter.getCode()); } // 其他方法实现... }在字段上指定TypeHandlerTableField(typeHandler UserTypeHandler.class) private UserType userType;5. 性能对比测试使用JMH进行基准测试单位ops/ms数据量saveBatch改造后方案提升幅度100120450275%500253801420%1000123502816%5000228013900%测试环境MySQL 8.0连接池HikariCP机器配置4核8G6. 生产环境最佳实践监控指标执行时间阈值报警超过1秒批次大小监控建议200-500条/批失败率监控超过1%需要预警熔断机制public class BatchInsertCircuitBreaker { private static final int FAILURE_THRESHOLD 5; private int failureCount 0; public boolean allowExecution() { return failureCount FAILURE_THRESHOLD; } public void recordFailure() { failureCount; } public void recordSuccess() { failureCount 0; } }灰度发布策略先对10%的流量启用新方案监控1小时无异常后全量数据验证public void validateBatch(ListUser users) { if (users null || users.isEmpty()) { throw new IllegalArgumentException(数据不能为空); } if (users.size() 1000) { throw new IllegalArgumentException(单批次不得超过1000条); } // 其他业务规则校验... }7. 扩展思考如何支持多数据源对于使用dynamic-datasource等多数据源场景需要特别注意在自定义方法上添加DS注解public interface UserMapper extends BaseMapperUser { DS(slave_1) int insertBatchSomeColumn(ListUser users); }事务管理器配置Bean public PlatformTransactionManager transactionManager(DynamicDataSource dataSource) { return new DataSourceTransactionManager(dataSource); }连接泄漏防护public void batchInsertMultiDS(ListUser users) { try { // 操作逻辑 } finally { DynamicDataSourceContextHolder.clear(); } }在实际项目中我建议将批量插入操作封装成独立的Service这样既能保持代码整洁又方便统一管理事务和异常处理。一个经验法则是单批次数据量控制在300-500条总执行时间不超过1秒这样的配置在大多数场景下都能取得不错的平衡。

相关新闻

Agent 评测的基本概念与经典方法

Agent 评测的基本概念与经典方法

背景 现如今想要搭建一个 Agent,其实并不是很复杂,已经有非常多成熟的框架和架构选型。但是,很多人会遇到同一个问题:Agent 构建好之后,到底应该怎么评测? Agent 的评测的确是一个比较复杂的事情&#xff0…

2026/8/3 1:49:19阅读更多 →
成为管理者提前学习的能力

成为管理者提前学习的能力

个体贡献者需提前培养管理特质,企业有明确的管理晋升观察维度。 来自抖音:https://www.douyin.com/user/self?from_tab_namemain&modal_id7668281846778865075&showSubTabvideo&showTabfavorite_collection 1.提前培养缘由 现代管理先有行…

2026/8/3 1:49:19阅读更多 →
Linux 入门指南:从零基础到玩转命令行 12

Linux 入门指南:从零基础到玩转命令行 12

Linux 硬盘分区管理 主要分为 MBR 和 GPT 分区 主引导扇区由三个部分组成: MBR-Master Boot Record 在 linux 中,管理员可以创建最多15个分区 每个分区最大不超过 2T GPT分区方案最多可提供128个分区。 LBA0(保护性MBR)&…

2026/8/3 1:49:19阅读更多 →
Langchain4j分布式链路监控实战:从原理到落地

Langchain4j分布式链路监控实战:从原理到落地

1. 项目概述:Langchain4j链路检测的必要性在分布式系统架构中,一个Langchain4j项目的调用链路可能涉及多个微服务、数据库查询和外部API调用。最近在排查一个生产环境问题时,我们发现某个AI推理请求耗时异常,但由于缺乏全链路追踪…

2026/8/3 6:16:20阅读更多 →
从单机到高可用集群:VMware ESXi+vCenter企业级虚拟化实战部署指南

从单机到高可用集群:VMware ESXi+vCenter企业级虚拟化实战部署指南

1. 项目概述:从单机到集群的虚拟化跃迁几年前,我还在为几台物理服务器上跑着十几个应用而头疼。每次硬件维护、系统升级都像是一场灾难,业务中断、数据迁移、兼容性测试,哪一样都让人心力交瘁。后来,VMware ESXi 单机版…

2026/8/3 6:16:20阅读更多 →
ThreadLocal 不是银弹:一次内存泄漏把老年代打满的复盘

ThreadLocal 不是银弹:一次内存泄漏把老年代打满的复盘

引子:为什么人人都用 ThreadLocalWeb 开发里 ThreadLocal 几乎无处不在:Spring 的 RequestContextHolder、MyBatis 的 PageHelper、日志链路追踪的 traceId,底层都靠它把"只属于当前请求"的数据绑在线程上,免去一层层传…

2026/8/3 6:16:20阅读更多 →
学生党如何低成本选择AI工具:去AIGC与率零对比

学生党如何低成本选择AI工具:去AIGC与率零对比

1. 项目概述:学生党如何低成本选择AI工具去年我在准备毕业论文时,曾经连续两周每天花5小时对比各种AI工具的价格和性能。作为每月生活费只有1500元的穷学生,我深刻理解在预算有限的情况下选择AI工具的纠结。现在市面上主流的"去AIGC&quo…

2026/8/3 6:16:20阅读更多 →
Klick‘r深度解析:Android图像识别自动点击工具架构剖析

Klick‘r深度解析:Android图像识别自动点击工具架构剖析

Klickr深度解析:Android图像识别自动点击工具架构剖析 【免费下载链接】Smart-AutoClicker An open-source auto clicker on images for Android 项目地址: https://gitcode.com/gh_mirrors/smar/Smart-AutoClicker Klickr是一款基于图像识别技术的Android自…

2026/8/3 6:16:20阅读更多 →
MouseClick鼠标连点器:告别重复点击的5分钟终极指南

MouseClick鼠标连点器:告别重复点击的5分钟终极指南

MouseClick鼠标连点器:告别重复点击的5分钟终极指南 【免费下载链接】MouseClick 🖱️ MouseClick 🖱️ 是一款功能强大的鼠标连点器和管理工具,采用 QT Widget 开发 ,具备跨平台兼容性 。软件界面美观 ,操…

2026/8/3 6:14:19阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/3 0:29:53阅读更多 →
限时公开!某头部SaaS公司内部AI模板工厂架构文档(含5类行业模板源码+性能压测报告)

限时公开!某头部SaaS公司内部AI模板工厂架构文档(含5类行业模板源码+性能压测报告)

更多请点击: https://intelliparadigm.com 第一章:AI模板批量生成的核心价值与落地全景 AI模板批量生成正从实验性工具演进为现代软件工程的关键基础设施。它通过语义理解、上下文感知与结构化约束,将重复性高、模式明确的代码/文档/配置生成…

2026/8/3 0:33:53阅读更多 →
如何快速找回消失的网页:Web Archives浏览器扩展终极指南

如何快速找回消失的网页:Web Archives浏览器扩展终极指南

如何快速找回消失的网页:Web Archives浏览器扩展终极指南 【免费下载链接】web-archives Browser extension for viewing archived and cached versions of web pages, available for Chrome, Edge and Safari 项目地址: https://gitcode.com/gh_mirrors/we/web-a…

2026/8/3 0:20:37阅读更多 →
3个让你工作效率翻倍的Umi-OCR实战技巧:免费离线文字识别完全指南

3个让你工作效率翻倍的Umi-OCR实战技巧:免费离线文字识别完全指南

3个让你工作效率翻倍的Umi-OCR实战技巧:免费离线文字识别完全指南 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片,PDF文档识别,排除水印/页眉页脚,扫描/生成二维码。…

2026/8/3 0:00:32阅读更多 →
[具身智能-181]:PC+服务器+具身机器人:构建具身智能从仿真到量产的闭环迭代混合架构

[具身智能-181]:PC+服务器+具身机器人:构建具身智能从仿真到量产的闭环迭代混合架构

PC服务器具身机器人:构建具身智能从仿真到量产的闭环迭代混合架构一、前言:具身智能需要“混合算力闭环系统”传统人工智能依赖云端静态数据集训练,不具备物理交互能力,无法适应真实世界的不确定性。具身智能(Embodied…

2026/8/3 0:00:32阅读更多 →
[具身智能-181]:大分布式通信模型对比:看懂为什么 DDS 是 ROS2 底层通信最优解

[具身智能-181]:大分布式通信模型对比:看懂为什么 DDS 是 ROS2 底层通信最优解

前言构建机器人、具身智能这类分布式实时系统,通信底座直接决定整套系统的实时性、容错性、组网能力。分布式领域长期存在 4 类经典通信架构:点对点模式、Broker 中间代理模式、广播模式、以数据为中心(DDS)模式。很多开发者疑惑&…

2026/8/3 0:00:32阅读更多 →
无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理 【免费下载链接】lossless-cut The swiss army knife of lossless video/audio editing 项目地址: https://gitcode.com/gh_mirrors/lo/lossless-cut 在数字媒体创作领域,视频编辑处理的质量损…

2026/8/3 2:32:59阅读更多 →
AI辅助本科论文写作:8大工具评测与高效使用指南

AI辅助本科论文写作:8大工具评测与高效使用指南

1. 本科生论文写作的AI辅助现状本科毕业论文是每个大学生必须跨越的一道坎。记得我当年写论文时,光是文献检索就花了整整两周时间,打印的参考文献堆满了半个书桌。如今AI技术的发展为学术写作带来了革命性变化,合理使用这些工具可以节省80%以…

2026/8/3 2:33:01阅读更多 →
如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 还在为抢不到热门演唱会门票…

2026/8/3 2:33:04阅读更多 →