2016-09-19 25 views
4

我有200K行插入到一個單一的數據庫表中。我試圖在春季使用jdbcTemplate.batchUpdate,以便每批插入10,000個。但是,這個過程會消耗太多時間(200K行7分鐘)。所以在數據庫方面,我檢查了select count(*) from table_X插入的行數。我發現行數增加了10K的預期。任何人都可以解釋什麼是理由,還是應該在數據庫端配置的東西?爲什麼彈簧jdbcTemplate batchUpdate逐行插入

PS:我使用Sybase ....

+0

顯示你的代碼,您使用的BatchPreparedStatementSetter?你在你的服務或DAO上使用@Transactional註釋嗎? –

+0

@SheetalMohanSharma而不是使用spring,我切換到本地jdbc api並自己處理transactioin。它現在有效。雖然它仍然很慢.... –

+0

有效我刪除@Transactional註釋可能會導致問題....但我刪除它,以加速insection。 ...它沒有幫助 –

回答

1

嘗試連接字符串下面設置 - useServerPrepStmts=false&rewriteBatchedStatements=true。沒有嘗試,但它從我的書籤。您可以搜索這些行..

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

它看起來像它不' t工作的sybase :( –

+0

嗯,但仍然檢查該帖子和該帖子中的鏈接 - 它可能會幫助 –

+0

是的謝謝你的建議,我會更新這個職位,當我找到一個解決方案 –

5

有很多方法可用於網絡。 性能直接取決於你所寫的

  1. 代碼
  2. 您使用
  3. 數據庫服務器和連接的數量您使用
  4. 表索引
  5. JDBC驅動程序導致了緩慢插入

沒有看任何人都可以猜到你的代碼,但沒有人能找到確切的解決方案。

方法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); 
} 
Alternatively, you can execute the SQL directly. 

//insert batch example with SQL 
public void insertBatchSQL(final String sql){ 

    getJdbcTemplate().batchUpdate(new String[]{sql}); 

} 

refernce

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*/ 
+0

感謝您的答覆。我的代碼是方法3使用原生的JDBC準備語句,實際上插入是通過包含10K行的批處理有效地完成的,但是10K行需要25到30秒才能終止,這是不可接受的:( –

+0

我使用的是Sybase 15.5,並且猜測它可能是Sybase的問題,因爲我用PostgreSQL用相同的代碼進行了測試,PostgreSQL在10K行上的時間不到1秒,我曾經向DBA團隊徵求意見,感謝上面的例子。 –