Oracle 23c에 Automatic SQL Transpiler 기능이 추가되었습니다. 해당 기능은 단순 표현식을 반환하는 PL/SQL 함수를 SQL 표현식으로 변환해 SQL과 PL/SQL 간의 Context switching을 제거함으로써 성능을 개선합니다.
PL/SQL functions within SQL statements are automatically converted (transpiled) into SQL expressions whenever possible. Transpiling PL/SQL functions into SQL statements can speed up overall execution time.
테스트를 위해 아래와 같이 테이블과 함수를 생성하겠습니다. f1 함수는 단순 표현식을 반환합니다.
-- 1-1 DROP TABLE t1 PURGE; CREATE TABLE t1 (c1, c2) AS SELECT ROWNUM, ROWNUM FROM XMLTABLE ('1 to 1000000'); -- 1-2 CREATE OR REPLACE FUNCTION f1 (i_v1 IN NUMBER) RETURN NUMBER IS BEGIN RETURN i_v1 + 1; END; /
Automatic SQL Transpiler 기능을 활성화하려면 sql_transpiler 파라미터를 ON으로 설정해야 합니다.
-- 2-1 SELECT name, value, default_value, description FROM v$parameter_valid_values WHERE name = 'sql_transpiler'; NAME VALUE DEFAULT_VALUE DESCRIPTION -------------- ----- ------------- --------------------- sql_transpiler OFF OFF Enable SQL transpiler 1개의 행이 선택되었습니다. -- 2-2 SELECT ordinal, value, isdefault FROM v$parameter_valid_values WHERE name = 'sql_transpiler'; ORDINAL VALUE ISDEFAULT ------- ----- --------- 1 ON FALSE 2 OFF TRUE 2 행이 선택되었습니다.
sql_transpiler 파라미터를 ON으로 설정하고 f1 함수를 사용한 쿼리를 수행하면 수행에 0.08초가 소요됩니다. Predicate Information 항목에서 f1 함수가 "C1" + 1 표현식으로 변환된 것을 확인할 수 있습니다.
-- 3 ALTER SESSION SET sql_transpiler = 'ON'; SELECT /* TEST1 */ SUM (f1 (c1)) FROM t1 WHERE f1 (c1) > c2; ------------------------------------------------------------------- | Id | Operation | Name | A-Rows | A-Time | Buffers | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 |00:00:00.08 | 2078 | | 1 | SORT AGGREGATE | | 1 |00:00:00.08 | 2078 | |* 2 | TABLE ACCESS FULL| T1 | 1000K|00:00:00.04 | 2078 | ------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("C2"<"C1"+1)
10053 트레이스에서 변환된 쿼리를 확인할 수 있습니다.
-- 4 Final query after transformations:******* UNPARSED QUERY IS ******* SELECT SUM("T1"."C1"+1) "SUM(F1(C1))" FROM "TUNA"."T1" "T1" WHERE "T1"."C2"<"T1"."C1"+1
sql_transpiler 파라미터를 OFF로 설정하고 동일한 쿼리를 수행하면 수행에 2.02초가 소요됩니다. Predicate Information 항목에서 함수가 표현식으로 변환되지 않은 것을 확인할 수 있습니다.
-- 5 ALTER SESSION SET sql_transpiler = 'OFF'; SELECT /* TEST2 */ SUM (f1 (c1)) FROM t1 WHERE f1 (c1) > c2; ------------------------------------------------------------------- | Id | Operation | Name | A-Rows | A-Time | Buffers | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 |00:00:02.02 | 2078 | | 1 | SORT AGGREGATE | | 1 |00:00:02.02 | 2078 | |* 2 | TABLE ACCESS FULL| T1 | 1000K|00:00:01.04 | 2078 | ------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("C2"<"F1"("C1"))
21.3 버전에 추가된 스칼라 유형의 SQL Macro를 사용해도 단순 표현식을 반환하는 PL/SQL 함수를 SQL 표현식으로 변환할 수 있습니다. 아래와 같이 f2 함수를 생성하겠습니다.
-- 6 CREATE OR REPLACE FUNCTION f2 (i_v1 IN NUMBER) RETURN VARCHAR2 SQL_MACRO (SCALAR) IS BEGIN RETURN 'i_v1 + 1'; END; /
f2 함수를 사용한 쿼리를 수행하면 수행에 0.08초가 소요됩니다. Predicate Information 항목에서 f1 함수가 "C1" + 1 표현식으로 변환된 것을 확인할 수 있습니다.
-- 7 SELECT /* TEST3 */ SUM (f2 (c1)) FROM t1 WHERE f2 (c1) > c2; ------------------------------------------------------------------- | Id | Operation | Name | A-Rows | A-Time | Buffers | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 |00:00:00.08 | 2078 | | 1 | SORT AGGREGATE | | 1 |00:00:00.08 | 2078 | |* 2 | TABLE ACCESS FULL| T1 | 1000K|00:00:00.04 | 2078 | ------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("C2"<"C1"+1)
10053 트레이스에서 변환된 쿼리를 확인할 수 있습니다.
-- 8 Final query after transformations:******* UNPARSED QUERY IS ******* SELECT SUM("T1"."C1"+1) "SUM(F2(C1))" FROM "TUNA"."T1" "T1" WHERE "T1"."C2"<"T1"."C1"+1