Java分批插入需按500~2000条切分,MySQL常用1000条/批;用subList切分并注意边界;每批用PreparedStatement+executeBatch执行,关闭自动提交,执行后clearBatch并commit,异常时rollback,finally释放资源。

Java 中处理大量数据的分批插入,核心是避免内存溢出、降低数据库锁竞争、提升吞吐量,同时保障事务一致性。关键不在于“一次插完”,而在于“分得合理、控得住、收得稳”。
按固定批次大小切分数据
这是最常用也最可控的方式。把原始数据列表按每 500~2000 条一组切分,每组开启独立事务执行批量插入。
- 批次大小建议:MySQL 常用 1000,SQL Server 推荐 500~1000,Oracle 可设为 200~500;过大易触发锁等待或 OOM,过小则失去批量意义
- 切分时用 subList 配合循环索引,注意边界判断(最后一组长度可能不足)
- 每批执行后调用 clearBatch() 和 commit(),再重置 PreparedStatement
用 PreparedStatement + executeBatch 控制执行
比 Statement 更安全高效,能复用 SQL 解析结果,防止 SQL 注入,也支持参数绑定。
- 务必关闭自动提交:conn.setAutoCommit(false)
- 每次循环中设置参数后调用 addBatch(),达到批次阈值即执行 executeBatch()
- 执行后必须调用 clearBatch(),否则下次 addBatch 会累积旧数据
- 异常时需 rollback(),并确保 finally 块中释放 Connection/PreparedStatement
结合 MyBatis 的 foreach 批量写法
适合中小规模(
立即学习“Java免费学习笔记(深入)”;
- XML 中用 <foreach> 拼接多组 VALUES,如:
INSERT INTO user (name) VALUES (#{item.name}), (#{item.name})... - 单次 SQL 最多支持约 65535 个参数(MySQL 默认 max_allowed_packet 限制),超限会报错
- 不适用于字段含 NULL 或需要动态逻辑判断的场景;也不便于监控每批进度或单独重试
大容量场景优先考虑数据库原生命令
当数据量达百万级以上,且来源为文件或可导出格式时,绕过 JDBC 层直接用数据库工具,性能差距可达数量级。
- MySQL:使用 LOAD DATA INFILE,配合本地文件 + 字段分隔符,速度最快
- PostgreSQL:用 COPY 命令,支持 STDIN 或文件导入
- SQL Server:支持 BULK INSERT 或表值参数(TVP),后者可在 Java 中构造 DataTable 传入
- 注意权限、路径、字符集和安全策略(如 local_infile 在 MySQL 中默认关闭)


















