Как прагма UDF работает?
Недавно прочёл о методе оптимизации с прагмой UDF в версии 12c.
Интересуюсь, как же это в точности работает. Нашёл только очень короткое описание в оф. документации:
The UDF pragma tells the compiler that the PL/SQL unit is a user defined function that is used primarily in SQL statements, which might improve its performance.
Как я понял, каждая прагма в PL/SQL это своего рода деректива компилятору (но точно не уверен) подобная C++ Pragma Directives.
Может кто-то более детально объяснить, какой внутренний механизм работы UDF прагмы?
Свободный перевод How Pragma UDF works? от участника @Oiale
Ответы (2 шт):
Внутренние детали работы компилятора PL/SQL нам не доступны, но в основном, прагма UDF это деректива компилятору, что нужно уделить больше внимания снижению затрат на переключение контекста вызова между PL/SQL и SQL.
Смею предположить, что эта прагма пользуется тем же преимущестом, которое получили PL/SQL функции напрямоую встроенные в CTE (Common Table Expression), например:
WITH function myfunction(x int) return int as
begin
return x;
end;
select myfunction (n) from mytable
PL/SQL функции как показано выше, действуют на время выполнения SQL запроса, выполняются с повышенными характеристиками производительности по сравнению с обычными сохранёнными функциями. Подозреваю, что UDF прагма позволяет пустить выполненение обычной PL/SQL функцию тем же путём, каким и выполняются встроенные в CTE.
(Но это мои личные предположения).
Свободный перевод ответа от участника @Connor McDonald
В документации в гл. 2.2.4 Pragmas сказано буквально следующее:
A pragma is an instruction to the compiler that it processes at compile time.
Oracle БД это продукт с закрытым кодом, поэтому больше чем написано в документации или получено опытым путём, о внутренних механизмах работы неизвестно.
Цель UDF прагмы - приблизить быстродействие пользовательских PL/SQL функций (UDF - user defined function) выполлняемых в основном в SQL контексте к нативно встроенным в SQL интерпретатор.
Фразу из документации - which might improve its performance, следует понимать буквально - может улучшить производительность, а может и нет. В различных блогах можно найти тесты, которые с различной комбинацией типов данных параметров и возврата не привели к ожидаемому приросту производительности. Предложение об улучшении уже поступило, когда будет реализовано - пока неясно.
Лучше убедится на конкретной функции, есть ли прирост производительности, например так:
create or replace function plspow2 (n number) return number is
begin return power (n, 2); end;
/
create or replace function udfpow2 (n number) return number is
pragma udf;
begin return power (n, 2); end;
/
create table t2 as
select level n from dual connect by level<=10e5;
declare
t number; c number; r number;
begin
t := dbms_utility.get_time;
c := dbms_utility.get_cpu_time;
select count(*) into r from t2 where n < power (n, 2);
dbms_output.put_line ('native SQL elapsed '||(dbms_utility.get_time-t)||' cpu '||(dbms_utility.get_cpu_time-c));
t := dbms_utility.get_time;
c := dbms_utility.get_cpu_time;
select count(*) into r from t2 where n < plspow2 (n);
dbms_output.put_line ('normal PLS elapsed '||(dbms_utility.get_time-t)||' cpu '||(dbms_utility.get_cpu_time-c));
t := dbms_utility.get_time;
c := dbms_utility.get_cpu_time;
select count(*) into r from t2 where n < udfpow2 (n);
dbms_output.put_line ('pragma UDF elapsed '||(dbms_utility.get_time-t)||' cpu '||(dbms_utility.get_cpu_time-c));
end;
/
native SQL elapsed 49 cpu 49
normal PLS elapsed 368 cpu 367
pragma UDF elapsed 100 cpu 100
Elapsed: 00:00:05.219