Oracle оптимизирует запросы, избегая курсоров - PullRequest
0 голосов
/ 02 сентября 2010

Я работаю над куском sql, который хочу оптимизировать. У меня внутри куча курсоров. Мне интересно, могу ли я использовать что-то еще вместо курсоров. Я думаю, используя какие-то переменные, заполняя их, и для остальной части лечения избегая соединения с БД (у меня комплексное лечение).

Например, у меня есть такой код:

TYPE rec_basket IS RECORD (
 FIELD1 VARCHAR2(40),
 FIELD2 NUMBER(10),
 FIELD3 VARCHAR2(6)
 );

 TYPE tab_basket IS TABLE OF rec_basket
 INDEX BY BINARY_INTEGER;

........................

CURSOR cur_baskets
   IS
select * from toto

............................

 FOR i IN cur_baskets
   LOOP
  l_tab_basket (l_nbasket).field1 := i.field1;
  l_tab_basket (l_nbasket).field2 := i.field2;
  l_tab_basket (l_nbasket).field3  := i.field3;
  l_nbasket := l_nbasket + 1;    
   END LOOP;

Использование курсора и заполнение переменной l_tab_basket - лучший путь? Я использую l_tab_basket (индекс) где-то в моем коде. Причина, по которой я поместил этот фрагмент кода, заключается в том, что я хотел бы использовать этот механизм для других моих курсоров. На самом деле у меня есть курсор внутри другого. И для каждой линии каждого из них у меня есть какое-то лечение. Я хотел бы заменить курсоры на что-то еще, но я не знаю как. Спасибо.

Ответы [ 2 ]

2 голосов
/ 02 сентября 2010

Вы можете использовать BULK COLLECT для извлечения всех записей во вложенную таблицу.Это будет работать в 10g +:

SQL> DECLARE
  2     TYPE rec_basket IS RECORD(
  3        field1 VARCHAR2(40),
  4        field2 NUMBER(10),
  5        field3 VARCHAR2(6));
  6     TYPE tab_basket IS TABLE OF rec_basket INDEX BY BINARY_INTEGER;
  7     l_tab_basket tab_basket;
  8  BEGIN
  9     SELECT 'a', ROWNUM, 'b'
 10       BULK COLLECT INTO l_tab_basket
 11       FROM dual CONNECT BY LEVEL <= 1000;
 12  END;
 13  /

PL/SQL procedure successfully completed

Имейте в виду, что Oracle 10g автоматически извлекает записи из неявных курсоров навалом (100) в pl / sql, поэтому выигрыш должен быть в лучшем случае минимальным: вы, вероятно, потратитебольше времени на запросы к БД, чем на построение массива, если массив не очень большой (и в этом случае целесообразно использовать вложенную таблицу?)

1 голос
/ 04 сентября 2010

Логика вашего кода не очень понятна.Вы не написали всю программу.Давайте рассмотрим:

CURSOR cur_baskets IS выбирает * из toto

Здесь значение считывается из таблицы toto и помещается в курсор.

В следующих строках значениячитаются из курсора и помещаются в l_tab_basket.

FOR i IN cur_baskets LOOP l_tab_basket (l_nbasket) .field1: = i.field1;l_tab_basket (l_nbasket) .field2: = i.field2;l_tab_basket (l_nbasket) .field3: = i.field3;l_nbasket: = l_nbasket + 1;
END LOOP;

Таким образом, одни и те же значения собираются в локальной переменной дважды.Этого можно избежать.Вы можете найти способы прямой вставки или обновления целевой таблицы.

Вы можете попробовать массовый сбор.Если toto мало, вы можете вставить или обновить целевую таблицу без использования курсора.

...