0

I want to optimize the performance of this SQL query. If I populate this hashtable with one million keys the query will take around minute. How I can optimize this Java method for faster execution?

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();
        }
    }
7
  • 1
    Do you want to optimize the SQL statement or the Java program? If it's the SQL query, how do you know it's the slow part? Did you time it? If so, what's the execution plan? Commented May 24, 2012 at 16:28
  • I want to optimize everything. Commented May 24, 2012 at 16:28
  • 2
    Do you need to get the IDs in Java? Can you compute the set of IDs in SQL and do the complete operation there? And a million SQL round-trips in a minute is pretty good! otherwise you could try batching the IDs into say 50 per SQL statement using WHERE ASESSIONID IN (?,?,.. etc. Commented May 24, 2012 at 16:28
  • 1
    This is a question for codereview.stackexchange.com Commented May 24, 2012 at 16:29
  • 1
    Well for a start you could iterate through selectedIds.entrySet() rather than turning the keys into an array and then looking up each key as you go. But frankly the Java isn't the problem: it's your approach to generating SQL, and/or pulling all of the IDs into Java in the first place when you could do all of this in the database. Commented May 24, 2012 at 16:48

4 Answers 4

5

If your JDBC driver supports it, use batch processing. It is easy to use, and tends to work very well for this type of scenarios.

Sign up to request clarification or add additional context in comments.

4 Comments

This is a Java Server Faces application hosted on Glassfish server. I don't know is this supported.
I agree batching is the way to go
He already has the commit after all the calls, so I don't think it will help much.
@ThorbjørnRavnAndersen: Actually, batch processing helps even if there's one commit in the end. What it does do is turn lots of tiny communications with the DBMS into few large ones.
3

Someone may have a better idea but have you considered passing a list of the keys to Oracle via a temp table and then performing the loop within a PL/SQL function. It will lower the traffic and the DB will do the processing.

Comments

2

Create a temporary table and insert all the ids into there. Then do a single delete for those found in t he temporary table.

Comments

2

I think it'd be better use CallableStatement and oracle procedure.

Snippet

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  /

2 Comments

Why - how would that solve the problem of passing all the IDs into the database? Why would that be better than prepared statements?
create an temp table according to your collection and hold the data into the table and delete data using in clause.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.