Производительность динамического SQL с Bind против обычного SQL в пакете - PullRequest
1 голос
/ 05 января 2009

В среде Oracle 10g у меня есть оператор, который должен выполняться несколько миллионов раз на основе результатов курсора. Для большей гибкости текущий код имеет оператор в виде константы в теле пакета. Вот упрощенная версия кода. Пожалуйста, имейте в виду, что это все в одном пакете:

c_Stmt  CONSTANT VARCHAR2(128) := 'DELETE FROM t WHERE fldA = :b1';

...

PROCEDURE p1(vSomeNumber NUMBER(10)) IS
BEGIN
  EXECUTE IMMEDIATE c_Stmt USING vSomeNumber;
END;

...

FOR i IN 1 .. 9999999
  LOOP
     p1(i);
  END LOOP;

Поскольку динамический SQL уже использует переменные связывания, есть ли какое-либо преимущество в производительности для переписывания этого кода, чтобы заменить динамический SQL обычным оператором DML, например так:

PROCEDURE p1(vSomeNumber NUMBER(10)) IS
BEGIN
  /* EXECUTE IMMEDIATE c_Stmt USING vSomeNumber; */
  DELETE FROM t WHERE fldA = vSomeNumber;
END;

Я думаю, что это может повлиять на количество разборов, но мне неясно, все еще ли это проблема в 10g.

Спасибо за ваши ответы.

Ответы [ 5 ]

2 голосов
/ 05 января 2009

Обычный SQL быстрее, чем динамический SQL (выполняется немедленно ...), но почему вы удаляете строки одну за другой? Почему бы не один большой оператор delete, который удаляет строки? Подумайте, основанный, а не ряд за строкой!

1 голос
/ 06 января 2009

В зависимости от конкретных потребностей у вас есть несколько вариантов повышения скорости удаления.

Во-первых, храните группу идентификаторов в массиве PL / SQL и периодически (и в конце) выполняйте либо УДАЛИТЬ массив FORALL, либо УДАЛЯТЬ ИЗ таблицы WHERE ID в (: arr (1),: arr (2) ...)

Во-вторых, сохраняйте идентификаторы в ГЛОБАЛЬНОЙ ВРЕМЕННОЙ ТАБЛИЦЕ и периодически / в конце выполняйте УДАЛЕНИЕ ИЗ таблицы, ГДЕ ИД В (ВЫБОР ИД ИЗ Global_temp_tbl)

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

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

В-четвертых, если издержки мягкого анализа значительны, но есть причина, по которой вы не хотите переключаться на статический SQL, вы можете использовать DBMS_SQL. Там DBMS_SQL.PARSE будет вне цикла, и только компоненты BIND_VARIABLE и EXECUTE будут внутри цикла.

1 голос
/ 05 января 2009

Одной из причин того, что второй метод (с помощью оператора Delete) будет быстрее, чем первый (с помощью Execute Immediate), является переключение контекста. Если вы выполните команду «Выполнить немедленно», процесс PL / SQL должен остановиться, Oracle должен загрузить процесс анализа, проанализировать вашу инструкцию (или извлечь ее из кэша операторов), а затем снова переключиться на процесс выполнения. С последним, есть на один раз меньше переключателей контекста.

Эти переключатели контекста (например, переключение потоков в многопоточных программах) отнимают много времени. По этой причине Oracle потратила немало времени, работая над тем, чтобы оператор массовой обработки (Bulk Insert, Bulk Select) работал правильно в PL / SQL.

Как предложено выше, попытайтесь заставить PL / SQL выполнить все операции удаления за один раз, например, путем создания списка идентификаторов для удаления в таблице PL / SQL и выполнения удаления в цикле FORALL. Меньше переключений контекста означает, что больше работы выполняется быстро.

1 голос
/ 05 января 2009

Как правило, более эффективно подготовить оператор перед циклом и выполнить дескриптор оператора во время цикла (предоставляя параметр в это время). Таким образом вы избежите накладных расходов при разборе и подготовке оператора каждый раз в цикле.

Использование статического SQL позволит избежать шага синтаксического анализа, поскольку это следует делать при определении процедуры. Но это не избавляет от накладных расходов на этапе подготовки.

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

0 голосов
/ 05 января 2009

Поскольку вы застряли в аду pl ​​/ sql, другой вариант - обновить строку, чтобы указать, что ее следует удалить.

Ваши текущие запросы могут игнорировать эти «мягко удаленные» строки.

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

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