2013-10-04 66 views
1

在我的應用程序中,我有一個包含大約200K條記錄的表,我需要在數據庫中進行更新。我認爲更快的方法是刪除數據庫中的所有匹配記錄並插入它們,而不是檢查每條記錄是否存在數據庫中的匹配記錄,然後插入或更新。我正在使用Spring JDBC框架。 要刪除,我用的JdbcTemplate BATCHUPDATE方法有ParameterizedPreparedStatementSetter沿和插入我使用SimplJdbcInsert。 插入工作正常,但是,批量刪除性能非常緩慢。 我不太確定採取什麼其他方法來刪除數據庫中的記錄並插入它們。任何建議都會非常有幫助。我使用SQL Server 2008 R2的Spring JDBC - 批量刪除和插入

ParameterizedPreparedStatementSetter<Order> vSetter = 
      new ParameterizedPreparedStatementSetter<Order>() { 
       @Override 
       public void setValues(PreparedStatement ps, 
         Order order) throws SQLException { 
        ps.setInt(1, order.getOrderNum()); 
       } 
    }; 

getJdbcTemplate().batchUpdate("DELETE FROM Order WHERE OrderNum = ?", 
      aDemandOrders, 
      50000, 
      vSetter); 
+1

我建議使用['MERGE'](http://msdn.microsoft.com/en-us/library/bb510625.aspx)而不是刪除然後插入。 –

+0

我最終做了更新並基於更新計數執行了插入操作。幫助提高了性能 – user320587

回答

1

的原因性能下降的是,DB將接收一批語句,而是由一個仍執行它們之一。

一種替代方法是使用in()子句和手動批量的語句,以允許DB與每個批量的執行一個語句。

爲了仍然得到查詢緩存的好處,但是你不能簡單地將所有在一個單一的in()條款,應分批予以適當。

private static final int MIN = 1; 
private static final int SML = 4; 
private static final int MED = 11; 
private static final int MAX = 51; 
private static final String DEL_ORDERS_QRY 
    = "DELETE FROM Order WHERE OrderNum in (:orders)"; 

public void deleteOrders(Collection<Integer> origIds) { 
    int done = getJdbcTemplate().execute((Connection con) -> { 
     // Reuse this query, `:orders` is a placeholder for the in-clause. 

     LinkedList<Integer> ids = new LinkedList<>(origIds); 
     int remainder = ids.size(); 
     int updated = 0; 

     while (remainder > 0) { 
      // identify the batch size for this execution. 
      int batchSize; 
      if (remainder >= MAX) { 
       batchSize = MAX; 
      } else if (remainder >= MED) { 
       batchSize = MED; 
      } else if (remainder >= SML) { 
       batchSize = SML; 
      } else { 
       batchSize = MIN; 
      } 
      remainder -= batchSize; 

      // Build the in-clause parameters. 
      StringBuilder inClause = new StringBuilder(batchSize * 2); 
      for (int i = 0; i < batchSize; i++) { 
       if (i > 0) { 
        inClause.append(','); 
       } 
       inClause.append('?'); 
      } 

      try (PreparedStatement ps = con.prepareStatement(
        DEL_ORDERS_QRY.replace(":orders", inClause.toString()))) { 
       for (int i = 0; i < batchSize; i++) { 
        ps.setInt(i + 1, ids.pop()); 
       } 
       updated += ps.executeUpdate(); 
      } catch (SQLException ex) { 
       log.error("Couldn't execute batch", ex); 
       throw new RuntimeException(ex.getMessage(), ex); 
      } 
     } 
     return updated; 
    }); 
}