在我的应用程序中,我有一个包含大约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;
});
}
关于java - Spring JDBC-批删除和插入,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19182477/