ResultSet.next () слишком медленный для курсора ссылки оракула

Я вызываю процедуру оракула из java, и в результате она возвращает курсор ref. Я помещаю указатель ref в ResultSet, и итерация начинается с него.

String query = "{call ...(...)}";
CallableStatement stmt = conn.prepareCall(query,ResultSet.TYPE_FORWARD_ONLY,
                ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(10000); 
.
.
.
stmt.registerOutParameter(x, OracleTypes.CURSOR);
stmt.execute();
Resultset rs = (ResultSet) stmt.getObject(x);

while (rs.next()) {    /** Problem occurs here **/
    ...
}

Проблема в том, что ИНОГДА (не всегда) для некоторых конкретных записей метод ResultSet.next () занимает слишком много времени (например, 100 секунд). Необходимо отметить, что количество возвращаемых записей не превышает 25, и тот же запрос в базе данных ведет себя нормально (выполняется примерно за 6 секунд).

По мере того, как я исследовал больше, я обнаружил, что в моем возвращенном курсоре есть столбец, при удалении которого эта проблема не возникает. Этот столбец на самом деле является ROWNUM (), который включен в курсор результата.

--ORACLE Query snippet:
OPEN result_cursor FOR 
SELECT "FirstName","LastName", r 
  FROM (SELECT ROWNUM r, *
         ... -- query details
         WHERE ROWNUM <= 25)

Я даже не касаюсь этого поля в ResultSet, но оно по-прежнему вызывает эту проблему (что кажется несправедливым :(). Я попытался преобразовать его в строку в процедуре Oracle (объединив ее с ''), предполагая, что тип преобразование могло вызвать эту проблему, но это не повлияло на ситуацию. почему это происходит?


person SJ.Jafari    schedule 19.11.2014    source источник
comment
Я полагаю, что установка такого большого размера выборки тратит память и может занять заметное время для настройки и разрушения структур. Вы исключаете r из окончательного списка выбора или удаляете фильтр rownum <= 25; по-видимому, у вас там order by, вы его тоже удаляете?   -  person Alex Poole    schedule 19.11.2014
comment
@AlexPoole: Я установил для размера выборки разные значения (10, 25, ...), и это не имело никакого значения. Я просто исключаю r из окончательного списка выбора, а тело запроса остается прежним. Я чувствую, что указатель ref на преобразование ResultSet вызывает эту проблему, но я не могу найти для этого причину.   -  person SJ.Jafari    schedule 19.11.2014
comment
Возможно, у вас плохой план выполнения запроса, который включает r; если у вас 10g, я бы задался вопросом о просмотре переменных привязки, особенно если он прерывистый. Можете ли вы проверить планы выполнения для обоих запросов (используя одинаковые значения привязки)?   -  person Alex Poole    schedule 19.11.2014
comment
Запустите трассировку оракула для сеанса и tkprof на нем.   -  person OldProgrammer    schedule 19.11.2014
comment
Я веду журнал до и после вызова SP в внешнем SP Oracle, и время журнала показывает, что SP был выполнен в надлежащее время на уровне БД. Кроме того, как я уже сказал, этого не происходит, когда SP вызывается из клиента db (например, navicat). Беру курсор в навигаторе и повторяю по нему, все в порядке, никто не пострадал. Но тот же вызов SP в java (с использованием JDBC) приводит к вышеупомянутой проблеме. Так что, похоже, это не проблема плана выполнения на стороне DB. Но я все равно последую вашим предложениям в поисках новых подсказок.   -  person SJ.Jafari    schedule 19.11.2014
comment
Совершенно дикая и, вероятно, глупая догадка: разве это не связано со сборкой мусора?   -  person Sylvain Leroux    schedule 19.11.2014


Ответы (1)


Поле, о котором вы говорите, ROWNUM (), является изменяемым значением, поскольку могут быть вставлены строки, которые могут фактически изменить абсолютный номер строки, который затем необходимо пересчитать при выполнении операции выборки, чтобы учесть любые вставки или удаления из таблиц, возвращаемых курсором с момента последнего вызова выборки. Вызов rs.next () каждый раз вызывает операцию выборки, потому что этот столбец является изменяемым значением, даже если вы получаете остальные результаты довольно быстро.

Это происходит из-за того, что использование курсора ref ПОДДЕРЖИВАЕТ ВЫБОР ОТКРЫТЫМ, пока вы перемещаетесь по ResultSet.

person Steve K    schedule 21.11.2014
comment
Что ж, это имеет смысл, но что может быть решением? - person SJ.Jafari; 21.11.2014
comment
Попробуйте выделить результат во временную таблицу и навести курсор на временную таблицу. - person Steve K; 22.11.2014
comment
Или просто верните обычный ResultSet, а не курсор. - person Steve K; 24.11.2014