Why Spring's jdbcTemplate.batchUpdate() so slow?

后端 未结 8 2308
终归单人心
终归单人心 2020-12-04 18:11

I\'m trying to find the faster way to do batch insert.

I tried to insert several batches with jdbcTemplate.update(String sql), wher

相关标签:
8条回答
  • 2020-12-04 19:13

    I had also some bad time with Spring JDBC batch template. In my case, it would be, like, insane to use pure JDBC, so instead I used NamedParameterJdbcTemplate. This was a must have in my project. But it was way slow to insert hundreds os thousands of lines in the database.

    To see what was going on, I've sampled it with VisualVM during the batch update and, voilà:

    visualvm showing where it was slow

    What was slowing the process was that, while setting the parameters, Spring JDBC was querying the database to know the metadata each parameter. And seemed to me that it was querying the database for each parameter for each line every time. So I just taught Spring to ignore the parameter types (as it is warned in the Spring documentation about batch operating a list of objects):

        @Bean(name = "named-jdbc-tenant")
        public synchronized NamedParameterJdbcTemplate getNamedJdbcTemplate(@Autowired TenantRoutingDataSource tenantDataSource) {
            System.setProperty("spring.jdbc.getParameterType.ignore", "true");
            return new NamedParameterJdbcTemplate(tenantDataSource);
        }
    

    Note: the system property must be set before creating the JDBC Template object. It would be possible to just set in the application.properties, but this solved and I've never after touched this again

    0 讨论(0)
  • 2020-12-04 19:16

    Simply use transaction. Add @Transactional on method.

    Be sure to declare the correct TX manager if using several datasources @Transactional("dsTxManager"). I have a case where inserting 60000 records. It takes about 15s. No other tweak:

    @Transactional("myDataSourceTxManager")
    public void save(...) {
    ...
        jdbcTemplate.batchUpdate(query, new BatchPreparedStatementSetter() {
    
                @Override
                public void setValues(PreparedStatement ps, int i) throws SQLException {
                    ...
    
                }
    
                @Override
                public int getBatchSize() {
                    if(data == null){
                        return 0;
                    }
                    return data.size();
                }
            });
        }
    
    0 讨论(0)
提交回复
热议问题