Java中JDBC批量插入海量数据的关键是控制交互节奏、复用预编译语句、减少事务开销;需用PreparedStatement调用addBatch()分批(500–1000条)、clearBatch()清空缓存,关闭自动提交并手动commit,且MySQL必须配置rewriteBatchedStatements=true。

Java 中用 JDBC 批量插入大量数据,关键不是“堆SQL”,而是控制交互节奏、复用编译、减少事务开销。单条插入百万数据可能要几十分钟,而正确配置下十几秒就能完成。
必须用 PreparedStatement + addBatch
不能用 Statement 拼接字符串再 addBatch,那样既不安全又没性能收益。PreparedStatement 支持预编译,避免每次执行都解析 SQL。操作流程是:
- 调用 connection.prepareStatement(sql) 创建语句对象
- 循环中用 pstmt.setString() 等设置参数,再调用 pstmt.addBatch()
- 每累积 500–1000 条(MySQL 场景推荐值)就调用一次 pstmt.executeBatch()
- 紧接着必须调用 pstmt.clearBatch(),否则后续 addBatch 会持续累加,内存暴涨
关闭自动提交,手动控制事务边界
默认 autoCommit=true 会让每次 executeBatch 都触发完整事务提交,I/O 和日志刷盘开销极大。应改为:
- conn.setAutoCommit(false)(获取连接后立即执行)
- 每执行一批(如 1000 条)不急着 commit,等累计到 5000 条左右或全部数据处理完再 conn.commit()
- 出错时调用 conn.rollback(),并确保 finally 块里恢复 autoCommit 或关闭资源
数据库驱动参数必须启用
对 MySQL 而言,rewriteBatchedStatements=true 是批处理提速的核心开关。它让驱动把多条 INSERT 合并成一条 INSERT INTO t VALUES (),(),() 发送,性能常提升 3–5 倍。JDBC URL 示例:
立即学习“Java免费学习笔记(深入)”;
jdbc:mysql://localhost:3306/db?rewriteBatchedStatements=true&useServerPrepStmts=false&serverTimezone=Asia/Shanghai注意:useServerPrepStmts=false 必须显式关闭,否则重写机制失效;该参数只对 INSERT 生效,UPDATE/DELETE 不起作用。
批大小与资源要平衡
500–2000 条/批是通用建议值。太大容易触发:
- OutOfMemoryError(驱动内部 batch 数组扩容失败)
- MySQL 的 max_allowed_packet 限制(拼出的 SQL 超长被拒)
- 事务日志膨胀,影响其他并发写入
若数据质量不稳定(如主键冲突较常见),可缩小到 200 条/批,便于快速定位失败记录。配合 HikariCP 等连接池使用,最小空闲连接数建议 ≥2,防止批量任务抢占不到连接。


















