为什么spring jdbcTemplate batchUpdate逐行插入

时间:2016-09-19 14:48:41

标签: java sql spring sybase jdbctemplate

我有200K行要插入一个数据库表中。我尝试在春天使用jdbcTemplate.batchUpdate,以便每批次插入10,000个。但是,此过程会消耗太多时间(对于200K行,为7分钟)。所以在数据库方面,我检查select count(*) from table_X插入的行数。我发现行数略有增加,预计为10K。任何人都可以解释是什么原因或者是应该在数据库端配置的东西吗?

PS:我正在使用sybase ....

3 个答案:

答案 0 :(得分:16)

网络上有很多方法可供使用。 性能直接取决于

  1. 您编写的代码
  2. 您正在使用的JDBC驱动程序
  3. 数据库服务器和您正在使用的连接数
  4. 表索引导致插入缓慢
  5. 没有看你的代码,任何人都可以猜到,但没有人能找到确切的解决方案。

    方法1

    //insert batch example
    public void insertBatch(final List<Customer> customers){
    
      String sql = "INSERT INTO CUSTOMER " +
        "(CUST_ID, NAME, AGE) VALUES (?, ?, ?)";
    
      getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() {
    
        @Override
        public void setValues(PreparedStatement ps, int i) throws SQLException {
            Customer customer = customers.get(i);
            ps.setLong(1, customer.getCustId());
            ps.setString(2, customer.getName());
            ps.setInt(3, customer.getAge() );
        }
    
        @Override
        public int getBatchSize() {
            return customers.size();
        }
      });
    }
    

    参考

    https://www.mkyong.com/spring/spring-jdbctemplate-batchupdate-example/

    http://docs.spring.io/spring-framework/docs/3.0.0.M4/reference/html/ch12s04.html

    方法2.1

    //insert batch example
    public void insertBatch(final List<Customer> customers){
        String sql = "INSERT INTO CUSTOMER " +
            "(CUST_ID, NAME, AGE) VALUES (?, ?, ?)";
    
        List<Object[]> parameters = new ArrayList<Object[]>();
    
        for (Customer cust : customers) {
            parameters.add(new Object[] {cust.getCustId(),
                cust.getName(), cust.getAge()}
            );
        }
        getSimpleJdbcTemplate().batchUpdate(sql, parameters);
    }
    

    或者,您可以直接执行SQL。

    //insert batch example with SQL
    public void insertBatchSQL(final String sql){
    
        getJdbcTemplate().batchUpdate(new String[]{sql});
    
    }
    

    推荐

    https://www.mkyong.com/spring/spring-simplejdbctemplate-batchupdate-example/

    方法2.2

    public class JdbcActorDao implements ActorDao {
        private SimpleJdbcTemplate simpleJdbcTemplate;
    
        public void setDataSource(DataSource dataSource) {
            this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
        }
    
        public int[] batchUpdate(final List<Actor> actors) {
            SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(actors.toArray());
            int[] updateCounts = simpleJdbcTemplate.batchUpdate(
                "update t_actor set first_name = :firstName, last_name = :lastName where id = :id",
                batch);
            return updateCounts;
        }
    
        //  ... additional methods
    }
    

    方法2.3

    public class JdbcActorDao implements ActorDao {
        private SimpleJdbcTemplate simpleJdbcTemplate;
    
        public void setDataSource(DataSource dataSource) {
            this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
        }
    
        public int[] batchUpdate(final List<Actor> actors) {
            List<Object[]> batch = new ArrayList<Object[]>();
            for (Actor actor : actors) {
                Object[] values = new Object[] {
                        actor.getFirstName(),
                        actor.getLastName(),
                        actor.getId()};
                batch.add(values);
            }
            int[] updateCounts = simpleJdbcTemplate.batchUpdate(
                    "update t_actor set first_name = ?, last_name = ? where id = ?",
                    batch);
            return updateCounts;
        }
    
        //  ... additional methods
    }
    

    方法3:JDBC

    dbConnection.setAutoCommit(false);//commit trasaction manually
    
    String insertTableSQL = "INSERT INTO DBUSER"
                + "(USER_ID, USERNAME, CREATED_BY, CREATED_DATE) VALUES"
                + "(?,?,?,?)";
    PreparedStatement = dbConnection.prepareStatement(insertTableSQL);
    
    preparedStatement.setInt(1, 101);
    preparedStatement.setString(2, "mkyong101");
    preparedStatement.setString(3, "system");
    preparedStatement.setTimestamp(4, getCurrentTimeStamp());
    preparedStatement.addBatch();
    
    preparedStatement.setInt(1, 102);
    preparedStatement.setString(2, "mkyong102");
    preparedStatement.setString(3, "system");
    preparedStatement.setTimestamp(4, getCurrentTimeStamp());
    preparedStatement.addBatch();
    preparedStatement.executeBatch();
    
    dbConnection.commit();
    

    refernce

    https://www.mkyong.com/jdbc/jdbc-preparedstatement-example-batch-update/

    /*Happy Coding*/
    

答案 1 :(得分:1)

尝试在下方设置连接字符串 - useServerPrepStmts=false&rewriteBatchedStatements=true。没有尝试,但从我的书签。你可以搜索这些行..

Connection c = DriverManager.getConnection("jdbc:<db>://host:<port>/db?useServerPrepStmts=false&rewriteBatchedStatements=true", "username", "password");

答案 2 :(得分:0)

对于我们将代码移动到包装类并使用@Transactional 注释批量插入方法确实解决了问题。