В оракуле явные курсоры загружают весь результат запроса в память?

У меня есть таблица с примерно 1 миллиардом строк. Я единственный пользователь, поэтому нет конфликтов с блокировками и т. Д. Я заметил, что когда запускаю что-то вроде этого:

DECLARE   
  CURSOR cur IS SELECT col FROM table where rownum < N; 
BEGIN
  OPEN cur;
  LOOP
    dbms_output.put_line("blah")
  END LOOP;
  CLOSE cur;
END;

есть задержка между моментом, когда я нажимаю клавишу ввода, и временем, когда вывод начинает поступать. Если N мало, то это незначительно. Для большого N (или отсутствия предложения WHERE) эта задержка составляет порядка нескольких часов.

Я новичок в оракуле, как вы можете сказать, и я предположил, что курсоры просто сохраняют указатель в таблице, которую они обновляют при каждой итерации цикла. Поэтому я не ожидал задержки, пропорциональной размеру таблицы, по которой выполняется итерация. Это неправильно? Загружают ли курсоры весь результат запроса до его повторения?

Есть ли способ перебирать таблицу построчно без начальных накладных расходов?


person pseudosudo    schedule 10.03.2010    source источник
comment
У вас есть LOOP без условия EXIT, какова цель этого бесконечного цикла?   -  person Vincent Malgrat    schedule 10.03.2010
comment
Вы правы, но код — это просто упрощенный скелет. Мой фактический код действительно завершается.   -  person pseudosudo    schedule 11.03.2010
comment
Можно было еще упростить: BEGIN null; END; :)   -  person Jeffrey Kemp    schedule 11.03.2010


Ответы (2)


Вы видите, что вывод DBMS_OUTPUT.PUT_LINE не отображается до тех пор, пока программа не завершится. Это ничего не говорит вам о том, как быстро запрос вернул первую строку. (Я предполагаю, что вы намеревались фактически получить данные в своем примере).

Есть много способов отслеживать сеанс, один из них такой:

DECLARE   
  CURSOR cur IS SELECT col FROM table; 
  l_col table.col%ROWTYPE;
BEGIN
  OPEN cur;
  LOOP
    FETCH cur INTO l_col;
    EXIT WHEN cur%NOTFOUND;
    dbms_application_info.set_module('TEST',l_col);
  END LOOP;
  CLOSE cur;
END;

Пока это выполняется, из другого сеанса:

select action from v$session where module='TEST';

Вы увидите, что значение ACTION продолжает меняться по мере того, как курсор выбирает строки.

person Tony Andrews    schedule 10.03.2010

Мне также нравится отслеживать v$session_longops для операций, которые оптимизатор Oracle считает «долгими операциями»:

выберите сообщение, time_remaining из v$session_longops, где time_remaining > 0;

person Dave    schedule 17.03.2010