批量插入性能提升10倍的关键是关闭自动提交、使用addbatch+executebatch、预编译preparedstatement、mybatis启用batch执行器,并配合mysql参数优化。

用对方式,批量插入性能翻 10 倍真不难。核心不是堆硬件或改数据库,而是绕开默认的“一条一提交”陷阱,把网络、事务、SQL 解析这三块开销一次性压下来。
关掉自动提交 + 手动用 addBatch
这是最基础也最关键的一步。JDBC 默认每执行一次 executeUpdate() 就自动提交一次事务,等于给数据库反复加锁、刷日志、写磁盘。
- 调用 connection.setAutoCommit(false) 关闭自动提交
- 循环中用 ps.addBatch() 把 SQL 参数攒起来,别急着执行
- 每积累 50–100 条再调一次 ps.executeBatch()
- 最后统一 connection.commit() 提交事务
换 PreparedStatement,别用 Statement
Statement 每次都要让数据库重新解析 SQL 字符串;PreparedStatement 预编译一次,后续只传参数,省下大量解析和执行计划生成时间。
- SQL 模板固定(如 INSERT INTO user (name, age) VALUES (?, ?)),就一定用 PreparedStatement
- 避免拼接字符串构造 SQL,既不安全也不利于预编译复用
- 配合连接池使用时,PreparedStatement 还能被缓存复用(如 HikariCP 的 cachePrepStmts=true)
MyBatis 项目直接上 ExecutorType.BATCH
如果你用的是 MyBatis 或 MyBatis-Plus,不用自己手写 JDBC,一行配置就能启用批处理引擎。
- 创建 SqlSession 时指定 ExecutorType.BATCH:sqlSessionFactory.openSession(ExecutorType.BATCH)
- Mapper 接口照常调用 insert() 方法,框架会自动攒批、复用 PreparedStatement
- 注意:BATCH 模式下,select 查询不可用,且必须手动 commit 或 close 才真正执行
- 搭配 @Transactional 使用要小心——Spring 默认代理会覆盖 ExecutorType,建议在非事务方法里做批量插入
MySQL 侧配合优化
后端优化到位了,数据库也得跟上节奏,否则容易卡在服务端。
- 开启 rewriteBatchedStatements=true(MySQL Connector/J 参数),它能把多个 ? ? ? 单条插入自动重写成多值 INSERT,比如:INSERT ... VALUES (?,?), (?,?)
- 调大 max_allowed_packet,防止大批量数据被截断
- 临时关闭唯一索引/外键检查(仅限导入场景):SET unique_checks=0; SET foreign_key_checks=0;,完事再打开
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











