今天本来打算学习java多线程异步任务处理,突发奇想如果向数据库插入大量数据该如何处理,顺便百度了一下,参考了这篇博客写的很好,于是我在本地试了一下
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Test
void contextLoads() throws SQLException {
// List<SysMenu> list = sysMenuService.getMenuByUserId(102L);
// log.info("");
// 10100010
List<Example> list = new ArrayList<>();
for (int i = 100010;i<=10100010;i++){
Example example = new Example();
example.setName("李四"+i);
example.setStatus("1");
list.add(example);
}
String sql = "insert into example (name,status) values (?,?)";
Connection conn = DriverManager.getConnection(url,username,password);
conn.setAutoCommit(false);
PreparedStatement ps = conn.prepareStatement(sql);
int count = 1;
Long time = 0L;
for (Example e:list){
ps.setString(1,e.getName());
ps.setString(2,e.getStatus());
ps.addBatch();
count++;
if (count % 100000 == 0){
Long start = System.currentTimeMillis();
ps.executeBatch();
conn.commit();
ps.clearParameters();
Long end = System.currentTimeMillis();
time = time + (end-start);
}
}
conn.close();
log.info("耗时"+(time)+"ms");
log.info("");
}
用的是@SpringBootTest来测试的
我一开始是一次性向数据库插入1000w条数据,发现报错了OutOfMemory异常
,因为我本生电脑也只有16个G,jvm堆内存装不下带有1000w数据的executeBatch,即不能一次性装下1000w条数据,故我设置了一个计数器count,每10w条数据,就像数据库提交数据,然后清空ps。
最后贴上结果。ok!!!