Давайте посмотрим, как, вероятно, будет обработана исходная версия.
FOR emp_rec in ( SELECT * from employee )
LOOP
SELECT * from Department WHERE id = emp_rec.DEPT_ID;
--write data from query to XML
END LOOP;
Запрос цикла может выполнить полное сканирование таблицы на employee
.Затем для каждой возвращаемой строки будет выполнен внутренний запрос.Предполагая, что id
является первичным ключом department
, при каждом выполнении запроса может выполняться уникальный поиск с использованием индекса первичного ключа.
Звучит отлично, верно?Поиск по уникальному индексу обычно является самым быстрым способом получения одной строки (за исключением явного поиска по ROWID).Но подумайте о том, что это делает в течение нескольких итераций цикла.Предположительно, каждый сотрудник принадлежит к отделу;в каждом отделе есть сотрудники;и большинство или все отделы имеют несколько сотрудников.
Таким образом, на нескольких итерациях цикла вы повторяете одну и ту же работу для внутреннего запроса несколько раз.Да, блоки данных могут быть кэшированы, поэтому вам не нужно повторять физическое чтение, но доступ к данным в кэше приводит к некоторым нагрузкам на ЦП, которые могут стать очень значительными, если к одним и тем же блокам обращаются снова и снова.
Кроме того, в конечном итоге вы, вероятно, захотите каждую строку в department
хотя бы один раз, а возможно, и более одного раза.Поскольку каждый отдельный блок в таблице нужно будет прочитать, вы на самом деле не экономите работу, выполняя поиск по индексу - вы добавляете работу.
Когда вы переписываете цикл как один запрос,оптимизатор может принять это во внимание.Один из возможных вариантов - объединение вложенных циклов, управляемое employee
, что по сути будет таким же, как явный цикл в PL / SQL (за исключением переключения контекста, как было отмечено Марком).Однако, учитывая взаимосвязь между двумя таблицами и отсутствие каких-либо предикатов фильтрации, оптимизатор сможет сказать, что более эффективно просто выполнить полное сканирование обеих таблиц и выполнить слияние или хэш-соединение.На самом деле это приводит к меньшему количеству физических операций ввода-вывода (при условии, что в начале каждого выполнения выполняется очистка кэша) и гораздо меньшему количеству логических операций ввода-вывода.