java jdbc批量插入大数据量的核心是控节奏、配参数、避陷阱;必须开启rewritebatchedstatements=true使驱动合并insert为多值语句,复用preparedstatement、批次1000–5000、手动事务控制。

Java 中用 JDBC 批量插入大量数据,核心不是“堆数量”,而是“控节奏、配参数、避陷阱”。单靠 addBatch() 不开启关键配置,性能几乎没提升;盲目塞几万条进 batch,反而容易 OOM 或被数据库拦截。
必须开启 rewriteBatchedStatements=true
MySQL 的 JDBC 驱动默认把 batch 当作多条独立语句发送,根本没真正批量。加这个参数后,驱动才会把多个 INSERT 合并成一条带多组 VALUES (..),(..) 的语句,大幅减少网络往返和 SQL 解析开销。
- 只对
PreparedStatement生效,Statement无效 - 仅对
INSERT有效,UPDATE/DELETE不重写 - 连接 URL 示例:
jdbc:mysql://host:3306/db?rewriteBatchedStatements=true&useServerPrepStmts=false(useServerPrepStmts=false必须关,否则重写失效)
合理控制每批条数(推荐 1000–5000)
太大易触发 max_allowed_packet 限制或内存溢出;太小则批处理收益不足。实际值要根据单行数据大小动态调整——字段越多、内容越长,批大小越要保守。
- 每累计 1000 条调一次
executeBatch(),之后立即clearBatch() - 示例逻辑:
if ((i + 1) % 1000 == 0) { ps.executeBatch(); ps.clearBatch(); } - 别等全部数据加完再执行,
addBatch()只是缓存,内部数组有上限(MySQL 驱动约 1024 条)
手动管理事务,别每批都 commit
每次 commit() 都会强制刷日志、落盘,I/O 开销极大。应把多个 batch 包在同一个事务里,等写入接近完成或达到安全阈值再统一提交。
- 开头设
conn.setAutoCommit(false) - 每 executeBatch 后暂不 commit,直到整批数据快写完
- 出错时调
conn.rollback(),注意executeBatch()返回的int[]中可能含Statement.EXECUTE_FAILED
坚持用 PreparedStatement 绑定参数
既防 SQL 注入,又让数据库复用执行计划。所有字段必须用 setString()、setInt() 等方法绑定,绝不拼接 SQL 字符串。
- 正确写法:
INSERT INTO user(name, age) VALUES (?, ?)+ps.setString(1, "Tom"); ps.setInt(2, 25) - 错误写法:
"INSERT INTO user VALUES ('" + name + "', " + age + ")"→ 危险且无法批处理 - 预编译一次,后续只传参,省去重复解析成本
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











