【问题标题】:Spring JDBC - Batch DELETE and INSERTSpring JDBC - 批量删除和插入
【发布时间】:2013-10-11 12:37:21
【问题描述】:

在我的应用程序中,我有一个包含大约 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);

【问题讨论】:

  • 我建议使用MERGE,而不是先删除再插入。
  • 我最终进行了更新,并根据更新计数执行了插入。大大提高了性能

标签: java jdbc spring-jdbc jdbctemplate


【解决方案1】:

性能慢的原因是DB会收到这批语句,但还是一个接一个地执行。

另一种方法是使用in () 子句并手动批处理语句,以允许数据库以每个批处理大小执行一条语句。

要仍然获得查询缓存的好处,但您不能简单地在单个 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;
    });
}

【讨论】:

    猜你喜欢
    • 2023-03-18
    • 2012-02-26
    • 1970-01-01
    • 1970-01-01
    • 2011-01-14
    • 1970-01-01
    • 2011-04-30
    • 2011-02-28
    相关资源
    最近更新 更多