JDBC向MS SQL批量插入10万条数据遇1000元素限制问题
我来分享下我用JDBC向MS SQL批量插入10万条姓名数据的实现方案——因为MS SQL限制单条INSERT语句最多包含1000个元素,所以我特意把数据集拆成了每组不超过1000条的子集来处理,同时用线程池优化插入效率:
实现思路
- 分批次处理: 每次从待插入列表中提取最多1000条数据,规避MS SQL的单条INSERT元素上限
- SQL语句拼接: 用
StringJoiner简化批量INSERT语句的构建,不用手动拼接繁琐的字符串 - 并行插入: 借助固定大小的线程池,让多个批次的插入任务并行执行,提升整体插入速度
代码实现
import java.util.HashSet; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.StringJoiner; import java.sql.Connection; import java.sql.Statement; public class BatchNameInserter { public void batchInsertNames(List<String> names) { // 初始化SQL拼接器,预设INSERT语句的前后部分,中间用'), ('分隔每个姓名 StringJoiner sqlJoiner = new StringJoiner("'), ('", "INSERT INTO Names (Name) VALUES ('", "');"); // 创建固定100线程的线程池,可根据数据库承载能力调整大小 ExecutorService threadPool = Executors.newFixedThreadPool(100); while (!names.isEmpty()) { // 每次取最多1000条数据,避免触发MS SQL的限制 int batchSize = Math.min(1000, names.size()); // 提取当前批次的姓名,用HashSet做批次内去重(如果原始数据无重复可省略) HashSet<String> currentBatch = new HashSet<>(names.subList(0, batchSize)); // 移除已处理的批次数据,避免重复插入 names.subList(0, batchSize).clear(); // 提交当前批次的插入任务到线程池 threadPool.submit(() -> { // 用try-with-resources自动管理JDBC资源,避免泄漏 try (Connection conn = /* 这里替换成你的JDBC连接获取逻辑 */; Statement stmt = conn.createStatement()) { sqlJoiner.reset(); currentBatch.forEach(sqlJoiner::add); String insertSql = sqlJoiner.toString(); // 执行批量插入 stmt.executeUpdate(insertSql); } catch (Exception e) { // 生产环境建议替换为日志记录+重试逻辑 System.err.println("批次插入失败: " + e.getMessage()); e.printStackTrace(); } }); } // 关闭线程池并等待所有任务完成 threadPool.shutdown(); try { // 设置超时时间,防止无限等待 if (!threadPool.awaitTermination(1, java.util.concurrent.TimeUnit.HOURS)) { threadPool.shutdownNow(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); threadPool.shutdownNow(); e.printStackTrace(); } } }
注意事项
- 资源管理: 务必用try-with-resources管理JDBC连接、Statement等资源,确保资源能被自动释放
- 线程池调优: 100线程的设置不是固定值,需要根据你的数据库连接池最大连接数调整,避免线程过多导致连接耗尽
- 异常处理: 代码里的异常处理只是基础示例,生产环境建议加入失败重试、错误数据记录等逻辑,方便后续排查和补插
- 去重逻辑: 如果原始姓名数据已经保证唯一,可以去掉
HashSet的转换,减少不必要的性能开销
内容的提问来源于stack exchange,提问作者Ploni Almoni
相关产品推荐
相关产品推荐

