我正在尝试找到更快的方法来进行批处理插入。
我尝试使用 jdbcTemplate.update(String sql) 插入多个批次,其中 sql 由 StringBuilder 构建,如下所示:
INSERT INTO TABLE(x, y, i) VALUES(1,2,3), (1,2,3), ... , (1,2,3)
批量大小正好是1000。我插入了近100个批次。 我使用秒表检查了时间并找出了插入时间:
min[38ms], avg[50ms], max[190ms] per batch
我很高兴,但我想让我的代码变得更好。
之后,我尝试以如下方式使用jdbcTemplate.batchUpdate:
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
// ...
}
@Override
public int getBatchSize() {
return 1000;
}
});
sql 看起来像这样
INSERT INTO TABLE(x, y, i) VALUES(1,2,3);
我很失望! jdbcTemplate 以单独的方式批量执行 1000 行的每一次插入。我查看了 mysql_log,发现有一千个插入。 我使用秒表检查了时间并找出了插入时间:
每批次最小[900ms],平均[1100ms],最大[2000ms]
那么,有人可以向我解释一下,为什么 jdbcTemplate 在这个方法中进行分离插入吗?为什么方法的名称是batchUpdate? 或者我可能以错误的方式使用这种方法?
JDBC 连接 URL 中的这些参数可以对批处理语句的速度产生很大影响 --- 根据我的经验,它们可以加快速度:
?useServerPrepStmts=false&rewriteBatchedStatements=true
参见:JDBC批量插入性能
我发现了重大改进在调用中设置argTypes数组。
在我的例子中,使用 Spring 4.1.4 和 Oracle 12c,插入 5000 行和 35 个字段:
jdbcTemplate.batchUpdate(insert, parameters); // Take 7 seconds
jdbcTemplate.batchUpdate(insert, parameters, argTypes); // Take 0.08 seconds!!!
argTypes 参数是一个 int 数组,您可以通过以下方式设置每个字段:
int[] argTypes = new int[35];
argTypes[0] = Types.VARCHAR;
argTypes[1] = Types.VARCHAR;
argTypes[2] = Types.VARCHAR;
argTypes[3] = Types.DECIMAL;
argTypes[4] = Types.TIMESTAMP;
.....
我调试了 org\springframework\jdb