当前位置: 首页 > 知识库问答 >
问题:

为什么是Spring的jdbcTemplate。batchUpdate()这么慢?

卢朝
2023-03-14

我正试图找到更快的批量插入方法。

我试图用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.batch更新的方式如下:

    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_日志中找到了上千个插入。我用秒表查看了时间,发现了插入时间:

每批最低[900ms],平均[1100ms],最高[2000ms]

那么,有谁能向我解释一下,为什么jdbcTemplate会在这种方法中进行单独的插入?为什么方法的名称是batchUpdate?或者可能是我用错了这个方法?

共有3个答案

酆恩
2023-03-14

我在使用Spring JDBC模板时也遇到了同样的问题。可能在SpringBatch中,语句在每次插入或块上执行和提交,这会减慢速度。

我已经替换了JDBC模板。batchUpdate()代码与原始JDBC批插入代码进行了比较,并发现了主要的性能改进。

DataSource ds = jdbcTemplate.getDataSource();
Connection connection = ds.getConnection();
connection.setAutoCommit(false);
String sql = "insert into employee (name, city, phone) values (?, ?, ?)";
PreparedStatement ps = connection.prepareStatement(sql);
final int batchSize = 1000;
int count = 0;

for (Employee employee: employees) {

    ps.setString(1, employee.getName());
    ps.setString(2, employee.getCity());
    ps.setString(3, employee.getPhone());
    ps.addBatch();

    ++count;

    if(count % batchSize == 0 || count == employees.size()) {
        ps.executeBatch();
        ps.clearBatch(); 
    }
}

connection.commit();
ps.close();

检查此链接以及JDBC批插入性能

微生毅
2023-03-14

我发现了一个主要的改进,在调用中设置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\jdbc\core\JdbcTemplate.java,发现大部分时间都花在试图了解每个字段的性质上,这是为每个记录制作的。

希望这有帮助!

柏高洁
2023-03-14

JDBC连接URL中的这些参数可以大大提高批处理语句的速度——根据我的经验,它们可以加快速度:

?UseServerPrepsmts=false

请参阅:JDBC批插入性能

 类似资料:
  • 有一个简单的要求,我必须对更新查询的对象列表进行batchUpdate。 问题是,运行代码后,在数据库表中,我只看到第一行得到更新,其余的没有得到更新。下面是我为此使用的示例代码。 公共void更新(列表列表){ } 如果我的列表大小为 N,我什至可以确认 setValues() 方法确实执行了 N 次。但是仍然执行批处理更新,在数据库中只更新第一行。我什至尝试更改列表中对象的顺序,结果仍然相同。

  • 问题内容: 我正在尝试找到批量插入的更快方法。 我试图用jdbcTemplate.update(String sql)插入几个批处理,其中sql是由StringBuilder 构建的,看起来像: 批次大小恰好是1000。我插入了近100批次。我使用秒表检查了时间,发现插入时间: 我很高兴,但是我想使代码更好。 在那之后,我尝试以如下方式使用jdbcTemplate.batchUpdate: sql

  • 我几天前听说了Docker的事,想过去看看。 但事实上,我不知道这个“容器”的用途是什么? 什么是容器? 它能取代一个专门用于开发的虚拟机吗? 简单地说,在公司中使用Docker的目的是什么?主要的优势?

  • 如果我运行deldeldel(“adel”),它会返回一个,但是,adel的长度是4,这意味着最后一个字符串索引是3,为什么str.substring(4,str.length()没有超出范围?

  • 问题内容: 以下面的代码为例: 示例1:我猜他们是同一对象。每次引用时,Python都会复制该方法吗? 示例2:预期。 示例3:预期,因为它们是不同的对象。 示例4:为什么此输出与示例2不匹配? 问题答案: 范例1: 是一种 未绑定的方法 。这些在当今的Python中甚至都不存在,因此请认为这是无用的历史课程。 每次引用时,Python都会复制该方法吗? 是的,或多或少。这是通过描述符协议完成的。

  • 问题内容: 这是所有编程语言所共有的吗?在进行多次打印后再执行println似乎更快,但是将所有内容移动到字符串中并仅进行打印似乎最快。为什么? 编辑:例如,Java可以在不到一秒钟的时间内找到所有高达100万的质数- 但要进行打印,然后在自己的println中将它们全部输出可能需要几分钟!最多可打印100亿小时! 例如: 问题答案: 速度并不慢,而是由主机操作系统提供的与控制台连接的基础。 您可