关于使用jdbcTemplate的PreparedStatement进行批量插入速度缓慢问题记录
最近公司项目使用jdbcTemplate的batchupdate方法进行批量数据插入,但是效率很慢,上源码String sqlStr = "INSERT INTO " + tableName + "(xh,timetemp,row_num) VALUES(?,?,?)";List<Object[]> batchArgs = new ArrayList<>();log.inf
·
最近公司项目使用jdbcTemplate的batchupdate方法进行批量数据插入,但是效率很慢,上源码
String sqlStr = "INSERT INTO " + tableName + "(xh,timetemp,row_num) VALUES(?,?,?)";
List<Object[]> batchArgs = new ArrayList<>();
log.info("开始循环赋值数据。。。");
for (BiTempYw entity : items) {
Object[] objects = new Object[3];
objects[0] = entity.getXh();
objects[1] = entity.getTimetemp();
objects[2] = entity.getRownum();
batchArgs.add(objects);
}
return new JdbcTemplate(dsm.getDataSource()).batchUpdate(sqlStr, batchArgs);
通过执行,发现在插入50000条数据时,耗时需要4分钟左右,因为项目中有许多的表需要执行,这样耗时太久,达不到要求,所以开始进行优化。
在网上查了许多文章,也看了很多的博客,其中大部分都是转载的,主要是在数据库连接的url中添加rewriteBatchedStatements=true的设置,但是这个只适用于mysql驱动,公司使用的是sqlserver,经过测试,无效。
也尝试过不使用jdbc封装,改用原生数据库连接并执行,但是依旧无效。
经过一系列尝试,最终发现,使用原生PreparedStatement的executeBatch()方法进行批量插入时,如果没有关闭自动提交,则在提交时,会不断的进行数据库commit操作,导致大量耗时。
经过修正后,代码如下:
String sqlStr = "INSERT INTO " + tableName + "(xh,row_num) VALUES(?,?)";
/*List<Object[]> batchArgs = new ArrayList<>();
for (BiTempOds entity : items) {
Object[] objects = new Object[2];
objects[0] = entity.getXh();
objects[1] = entity.getRownum();
batchArgs.add(objects);
}
return new JdbcTemplate(dsm.getDataSource()).batchUpdate(sqlStr, batchArgs);*/
Connection conn = null;
PreparedStatement ps = null;
try {
log.info("开始向临时表写入数据。。。");
conn = dsm.getDataSource().getConnection();
start=System.currentTimeMillis();
ps = conn.prepareStatement(sqlStr);
conn.setAutoCommit(false);
for (int i = 0; i <items.size(); i++) {
ps.setString(1, items.get(i).getXh());
ps.setInt(2, Objects.isNull(items.get(i).getRownum()) ? 0 : items.get(i).getRownum());
//将上述语句加入到批处理
ps.addBatch();
/*if (i % 1000 == 0) {
ps.executeBatch();
conn.commit();
ps.clearBatch();
}*/
}
ps.executeBatch();
conn.commit();
end=System.currentTimeMillis();
log.info("结束向临时表写入数据。。。,用时:" + (end-start));
} catch (SQLException e) {
log.error("向临时表写入数据错误", e.fillInStackTrace());
try {
conn.rollback();
} catch (SQLException ex) {
log.error("回滚conn连接错误", ex.fillInStackTrace());
}
}finally {
try {
ps.close();
} catch (SQLException e) {
log.error("关闭预编译语句发生异常: "+e.getMessage());
}
try {
conn.close();
} catch (SQLException e) {
log.error("关闭数据库链接发生异常: "+e.getMessage());
}
}
其中最主要的就是关闭自动提交
conn.setAutoCommit(false);
当然,关闭了自动提交功能,后面执行插入操作后,要手动提交和关闭。
经过测试,原先4分钟才能执行完成的数据,只需要1199ms,速度大大提升
至此记录,作为日后参考。
更多推荐
已为社区贡献1条内容
所有评论(0)