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