Oracle/Tuning2019. 1. 30. 09:10

사용자 정의 함수는 액세스 패스에 따라 수행 횟수가 달라질 수 있다. 관련 내용을 살펴보자.


테스트를 위해 아래와 같이 테이블과 함수를 생성하자.
-- 1
DROP TABLE t1 PURGE;
CREATE TABLE t1 AS SELECT LEVEL AS c1, LEVEL AS c2 FROM DUAL CONNECT BY LEVEL <= 10;
CREATE INDEX t1_x1 on t1 (c1);

CREATE OR REPLACE FUNCTION f1
RETURN NUMBER
IS
BEGIN
    DBMS_OUTPUT.PUT_LINE ('X');
    RETURN 1;
END;
/

아래 쿼리는 X가 1번 출력되었다. 함수 결과가 액세스 조건으로 사용되면 함수가 1번만 수행된다.

SET SERVEROUTPUT ON

-- 1
SELECT * FROM t1 WHERE c1 = f1;

-----------------------------------------------------
| Id  | Operation                           | Name  |
-----------------------------------------------------
|   0 | SELECT STATEMENT                    |       |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| T1    |
|*  2 |   INDEX RANGE SCAN                  | T1_X1 |
-----------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("C1"="F1"())

C1 C2
-- --
 1  1

1개의 행이 선택되었습니다.

X

아래 쿼리는 X가 10번 출력되었다. 함수 결과가 필터 조건으로 사용되면 함수가 행의 수만큼 수행된다.

-- 2
SELECT * FROM t1 WHERE c2 = f1;

----------------------------------
| Id  | Operation         | Name |
----------------------------------
|   0 | SELECT STATEMENT  |      |
|*  1 |  TABLE ACCESS FULL| T1   |
----------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("C2"="F1"())

C1 C2
-- --
 1  1

1개의 행이 선택되었습니다.

X
X
X
X
X
X
X
X
X
X

함수 결과가 필터 조건으로 사용될 경우 서브 쿼리를 통해 함수의 수행 횟수를 감소시킬 수 있다. 아래 쿼리는 함수에 서브 쿼리를 사용했다. X가 1번만 출력된 것을 확인할 수 있다.

-- 3
SELECT * FROM t1 WHERE c2 = (SELECT f1 FROM DUAL);

----------------------------------
| Id  | Operation         | Name |
----------------------------------
|   0 | SELECT STATEMENT  |      |
|*  1 |  TABLE ACCESS FULL| T1   |
|   2 |   FAST DUAL       |      |
----------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("C2"= (SELECT "F1"() FROM "SYS"."DUAL" "DUAL"))

C1 C2
-- --
 1  1

1개의 행이 선택되었습니다.

X


'Oracle > Tuning' 카테고리의 다른 글

TIMESTAMP 인덱스 - Right-Growing 경합 #1  (0) 2019.02.28
CLOB #6 - 블록 I/O  (0) 2019.02.27
SQL Patch  (0) 2019.01.09
SQL Profile  (0) 2019.01.09
다중 행 다중 열 스칼라 서브 쿼리의 부분 범위 처리  (0) 2019.01.09
Posted by 정희락_