[英]Spring JDBC - Batch DELETE and INSERT
在我的應用程序中,我有一個包含大約200K記錄的表,需要在數據庫中進行更新。 我認為無需檢查每個記錄是否在數據庫中存在匹配的記錄,然后進行插入或更新,而是一種更快的方法是刪除數據庫中所有匹配的記錄並插入它們。 我正在使用Spring JDBC框架。 要刪除,我使用了Jdbctemplate batchUpdate方法以及ParameterizedPreparedStatementSetter進行插入,而我使用的是SimplJdbcInsert。 插入工作正常,但是,批量刪除性能非常慢。 我不太確定應該采用什么其他方法刪除數據庫中的記錄並插入它們。 任何建議將非常有幫助。 我正在使用SQL Server 2008 R2
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);
性能低下的原因是,數據庫將接收該批語句,但仍將它們一一執行。
一種替代方法是使用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;
});
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.