Skip to content
Advertisement

Fetching Oracle DB LONG type through jdbc works very slow

This happens only when the statement return LONG column.
Even if i don’t do anything with it such like rs.getString, just execute.

sql1: That was: 7593 ms
sql2: That was: 530 ms

As you can see it’s not about volume of data.
When i use OracleConnection:OracleStatement:OracleCachedResultSet result is the same.
Also i tried to use OracleCachedRowSet instead of ResultSet.
Problem shows up in OracleCachedRowSet.execute() before OracleCachedRowSet.next().
When i set setFetchSize(1):

sql1: That was: 7474 ms
sql2: That was: 7153 ms

UPDATE 1:
I had tested other tools:

sql1# Toad For Oracle : execution time < 1 second
sql1# Oracle SQL Developer thin: 7.5 second(same as my result)
sql1# Oracle SQL Developer OCI: 7.5 second(same as my result)
sql2# Oracle SQL Developer thin: 0.36 second(same as my result)
Rows fethed one by one in sql1 case in java app, so look like setFetchSize() dosn’t work.

Sample code:

public class Test {

    public static void main(String[] args) throws SQLException {

        final String sql1 = "select HIGH_VALUE from sys.DBA_TAB_PARTITIONS WHERE rownum < 20";
        final String sql2 = "select PARTITION_NAME, HIGH_VALUE_LENGTH,TABLESPACE_NAME,NUM_ROWS,BLOCKS,n"
                + "EMPTY_BLOCKS,LAST_ANALYZED,AVG_SPACE,SUBPARTITION_COUNT,COMPRESSION from sys.DBA_TAB_PARTITIONS WHERE rownum < 20";

        OracleDataSource ods = new OracleDataSource();
        ods.setDriverType("thin");
        ods.setUser("vr");
        ods.setPassword("oracle");
        ods.setDatabaseName("ORCL");
        ods.setServerName("192.172.18.1");
        ods.setPortNumber(1521);

        Connection conn = null;
        conn = ods.getConnection();

        Statement stmt = conn.createStatement();
        stmt.setFetchSize(1000);

        // Start time
        long startTime = System.currentTimeMillis();

        ResultSet rs = stmt.executeQuery(sql1);
        rs.setFetchSize(1000);
        while (rs.next()){
            //System.out.println(rs.getString(1) + " " +  rs.getString(2));
            System.out.println("row#: " + rs.getRow());
        }

        // Finish time        
        long endTime = System.currentTimeMillis();
        System.out.println("That was: " + (endTime - startTime) + " ms");
    } 
}

Advertisement

Answer

Results with new ojdbc7.jar(before i used ojdbc6.jar from 11.2.0.2 bundle) and OracleJDBCRowSet.
19 rows:

sql1 : That was: 1470 ms // before 7-8 seconds
sql2 : That was: 1140 ms

99 rows:

sql1 : That was: 1491 ms
sql2 : That was: 1158 ms

As you can see its much faster, but still slower than query with even much more data.
Adding more column almost make no changes in execution and fetching time, so the problem partially solved.
But seems that the improvements comes to RowSets only.
OracleResultSet still work extremly slow.
Also if you link new driver with Oracle SQL Developer it takes no effect.

Sample code:

public class Test {

    public static void main(String[] args) {

        final String sql1 = "select HIGH_VALUE from sys.DBA_TAB_PARTITIONS WHERE rownum < 100";
        final String sql2 = "select PARTITION_NAME, HIGH_VALUE_LENGTH,TABLESPACE_NAME,NUM_ROWS,BLOCKS,n"
                + "EMPTY_BLOCKS,LAST_ANALYZED,AVG_SPACE,SUBPARTITION_COUNT,COMPRESSION "
                + "from sys.DBA_TAB_PARTITIONS WHERE rownum < 100";

        OracleDataSource ods = null;
        try {
            ods = new OracleDataSource();
        } catch (SQLException ex) {
            System.exit(2);
        }
        ods.setDriverType("thin");
        ods.setUser("vr");
        ods.setPassword("oracle");
        ods.setDatabaseName("ORCL");
        ods.setServerName("192.172.18.1");
        ods.setPortNumber(1521);

        try (Connection conn = ods.getConnection();) {
            try (OracleJDBCRowSet rs = new OracleJDBCRowSet(conn);) {
                rs.setFetchSize(200);
                rs.setReadOnly(true);
                rs.setCommand(sql2);

                // Start time
                long startTime = System.currentTimeMillis();

                rs.execute();
                while (rs.next()) {
                        System.out.println("row#: " + rs.getRow() + " " + rs.getString(1));
                }

                // Finish time        
                long endTime = System.currentTimeMillis();
                System.out.println("That was: " + (endTime - startTime) + " ms");
            }
        } catch (SQLException e) {
            System.err.println(e.getMessage());
        }
    }
}
3 People found this is helpful
Advertisement