Явные курсоры, использующие массовый сбор или неявные курсоры: есть проблемы с производительностью? - PullRequest
1 голос
/ 07 марта 2019

В более старой статье из журнала Oracle Magazine (теперь он-лайн как На курсоре для циклов ) Стивен Фюрштайн продемонстрировал оптимизацию для явного cursor for loops с использованием bulk collect (перечисление 4 в онлайн-статье):

DECLARE
  CURSOR employees_cur is SELECT * FROM employees;
  TYPE employee_tt IS TABLE OF employees_cur%ROWTYPE INDEX BY PLS_INTEGER;
  l_employees   employee_tt;
BEGIN
  OPEN employees_cur;
  LOOP
    FETCH employees_cur BULK COLLECT INTO l_employees LIMIT 100;
    -- process l_employees  using pl/sql only
    EXIT WHEN employees_cur%NOTFOUND;
  END LOOP;
  CLOSE employees_cur;
END;

Я понимаю, что bulk collect повышает производительность, поскольку между SQL и PL / SQL меньше переключений контекста.

Мой вопрос о неявном cursor for loops:

BEGIN
  FOR S in (SELECT * FROM employees)
  LOOP
    -- process current record of S
  END LOOP;
END;

Есть ли переключатель контекста в каждом цикле для каждой записи?Проблема такая же, как с явными курсорами, или она каким-то образом оптимизирована "за сценой"?Было бы лучше переписать код, используя явные курсоры с массовым сбором?

Ответы [ 2 ]

2 голосов
/ 07 марта 2019

Начиная с Oracle 10g, оптимизирующий компилятор PL / SQL может автоматически преобразовывать циклы FOR LOOP в циклы BULK COLLECT с размером массива по умолчанию, равным 100.

Поэтому обычно нет необходимости преобразовывать неявные циклы FOR в циклы BULK COLLECT..

Но иногда вы можете использовать вместо этого BULK COLLECT.Например, если размер массива по умолчанию в 100 строк на выборку не удовлетворяет вашим требованиям, ИЛИ если вы предпочитаете обновлять данные в наборе.

На тот же вопрос ответил Том Кайт.Вы можете проверить это здесь: Курсор для оптимизации циклов в 10g

0 голосов
/ 07 марта 2019

Да, даже если ваш -- process current record of S содержит чистый SQL и нет PL / SQL, у вас есть переключение контекста, поскольку FOR ... LOOP - это PL / SQL, но запрос - SQL.

По возможности вы должны предпочестьобрабатывать ваши данные с помощью отдельных операторов SQL (рассмотрим также MERGE , а не только DELETE, UPDATE, INSERT), в большинстве случаев они быстрее, чем построчная обработка.

Примечание,Вы не получите никакой производительности, если выполните цикл через l_employees и выполните DLL для каждой записи.

LIMIT 100 довольно бесполезен.Обработка только 100 строк одновременно была бы почти такой же, как обработка строк по очереди - Oracle не работает на Z80 с памятью 64 КБ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...