Извлечение Oracle DB LONG типа через jdbc работает очень медленно

1

Это происходит только тогда, когда оператор возвращает столбец LONG.
Даже если я ничего не делаю с ним, например rs.getString, просто выполните.

sql1: Это было: 7593 мс
sql2: Это было: 530 мс

Как вы можете видеть, это не объем данных.
Когда я использую OracleConnection: результат OracleStatement: OracleCachedResultSet тот же.
Также я попытался использовать OracleCachedRowSet вместо ResultSet.
Проблема появляется в OracleCachedRowSet.execute() перед OracleCachedRowSet.next().
Когда я устанавливаю setFetchSize (1):

sql1: Это было: 7474 мс
sql2: Это было: 7153 мс

ОБНОВЛЕНИЕ 1:
Я тестировал другие инструменты:

sql1 # Жаба для Oracle: время выполнения <1 секунда
sql1 # Oracle SQL Developer тонкий: 7,5 секунды (то же, что и мой результат)
sql1 # Oracle SQL Developer OCI: 7.5 секунд (так же, как и мой результат)
sql2 # Oracle SQL Developer тонкий: 0,36 секунды (то же, что и мой результат)
Строки, введенные один за другим в случае sql1 в java-приложении, так выглядят как setFetchSize() dosn't work.

Образец кода:

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");
    } 
}
  • 2
    так сколько времени это займет, если вы запустите его из клиента БД? Вы пытались объяснить план?
  • 1
    Когда я выполняю это от Жабы, это дает мне результат в данный момент. Я думаю, что это не о плане, потому что данные должны быть кэшированы после того, как я выполню инструкцию сотни раз. Но у меня есть идея сейчас. Я собираюсь попробовать это с Oracle SQL Developer, потому что он использует тот же драйвер, и я обновлю свой пост. Спасибо.
Показать ещё 3 комментария
Теги:
jdbc

1 ответ

1
Лучший ответ

Результаты с новым ojdbc7.jar (до того, как я использовал ojdbc6.jar из пакета 11.2.0.2) и OracleJDBCRowSet.
19 строк:

sql1: Это было: 1470 мс//до 7-8 секунд
sql2: Это было: 1140 мс

99 строк:

sql1: Это было: 1491 мс
sql2: Это было: 1158 мс

Как вы можете видеть, это намного быстрее, но все же медленнее, чем запрос с еще большим количеством данных.
Добавление большего количества столбцов почти не вносит изменений в выполнение и выбор времени, поэтому проблема частично решена.
Но кажется, что улучшения приходят только в RowSets.
OracleResultSet все еще работает очень медленно.
Также, если вы связываете новый драйвер с Oracle SQL Developer, это не имеет никакого эффекта.

Образец кода:

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());
        }
    }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню