【问题标题】:How to optimize this SQL delete如何优化此 SQL 删除
【发布时间】:2012-05-31 06:36:56
【问题描述】:

我想优化这个 SQL 查询的性能。如果我用一百万个键填充这个哈希表,查询将需要大约一分钟。如何优化此 Java 方法以加快执行速度?

private HashMap<String, Boolean> selectedIds = new HashMap<>();

public void deleteSelectedIDs() throws SQLException {

        if (ds == null) {
            throw new SQLException();
        }

        Connection conn = ds.getConnection();
        if (conn == null) {
            throw new SQLException();
        }

        PreparedStatement ps = null;
        ResultSet resultSet = null;

        try {
            conn.setAutoCommit(false);
            boolean committed = false;
            try {
                String sqlDeleteQuery = "DELETE FROM ACTIVESESSIONSLOG WHERE ASESSIONID = ?";

                Set<String> keySet = selectedIds.keySet();
                String[] keys = new String[]{};
                keys = selectedIds.keySet().toArray(keys);
                ps = conn.prepareStatement(sqlDeleteQuery);

                for (int i = 0; i < keys.length; i++) {
                    if (selectedIds.get(keys[i]).booleanValue()) {
                        ps.setString(1, keys[i]);
                        ps.executeUpdate();
                        ps.clearParameters();
                        selectedIds.put(keys[i], false); //get(keys[i]) = false;
                    }
                }

                conn.commit();
                committed = true;

                //selectedIds.clear();
            } finally {
                if (!committed) {
                    conn.rollback();
                }
            }
        } finally {
            ps.close();
            conn.close();
        }
    }

【问题讨论】:

  • 您要优化 SQL 语句还是 Java 程序?如果是 SQL 查询,你怎么知道它是慢的部分?你计时了吗?如果有,执行计划是什么?
  • 我要优化一切。
  • 您需要在 Java 中获取 ID 吗?你能在 SQL 中计算一组 ID 并在那里进行完整的操作吗?一分钟内一百万次 SQL 往返已经相当不错了!否则,您可以尝试使用 WHERE ASESSIONID IN (?,?,.. 等将 ID 批处理为每个 SQL 语句 50 个。
  • 首先,您可以遍历selectedIds.entrySet(),而不是将键转换为数组,然后随时查找每个键。但坦率地说,Java 不是问题:它是您生成 SQL 和/或首先将所有 ID 提取到 Java 中的方法,而您可以在数据库中完成所有这些操作。

标签: java sql oracle optimization


【解决方案1】:

如果您的 JDBC 驱动程序支持它,请使用 batch processing。它易于使用,并且在这种类型的场景中效果很好。

【讨论】:

  • 这是一个托管在 Glassfish 服务器上的 Java Server Faces 应用程序。我不知道这是否支持。
  • 我同意批处理是要走的路
  • 在所有调用之后他已经提交了,所以我认为这不会有太大帮助。
  • @ThorbjørnRavnAndersen:实际上,即使最后只有一个提交,批处理也会有所帮助。它所做的就是将与 DBMS 的大量微小通信转变为少数大型通信。
【解决方案2】:

有人可能有更好的主意,但您是否考虑过通过临时表将键列表传递给 Oracle,然后在 PL/SQL 函数中执行循环。它将降低流量,数据库将进行处理。

【讨论】:

    【解决方案3】:

    创建一个临时表并将所有 id 插入其中。然后对临时表中找到的内容执行一次删除。

    【讨论】:

      【解决方案4】:

      我认为最好使用 CallableStatement 和 oracle procedure

      片段

      SQL> create type temp_tbl
        2  is
        3  table of number;
        4  /
      
      ...
      
      
      SQL> create or replace procedure stored_p
        2  (
        3    list in temp_tbl,
        4    p_rc  out sys_refcursor )
        5  as
        6  begin
        7    open
        8   p_rc for delete from ACTIVESESSIONSLOG  where ASESSIONID
            in (select * from table(list));
        9  end;
       10  /
      

      【讨论】:

      • 为什么 - 这将如何解决将所有 ID 传递到数据库的问题?为什么这比准备好的陈述更好?
      • 根据您的集合创建一个临时表并将数据保存到表中并使用in子句删除数据。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2021-05-24
      • 1970-01-01
      • 1970-01-01
      • 2010-10-31
      • 2019-04-11
      相关资源
      最近更新 更多