오라클의 cursor_sharing = FORCE 의 폐혜
테스트 환경 : Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit
요점 : cursor_sharing = FORCE 환경에서 SQL문에 주어진 상수 마저 변수화 되므로 잘못된 실행 계획을 표현함
*/
-- 테스트를 위해서 아래와 같은 테이블 및 인덱스를 생성한다.
CREATE TABLE DNJSQO_T
(
C1 VARCHAR2(100) NOT NULL,
C2 NUMBER(10) NOT NULL
);
INSERT INTO DNJSQO_T
SELECT LPAD(LEVEL, 10, '0'), LEVEL
FROM DUAL
CONNECT BY LEVEL <= 10000;
COMMIT;
CREATE INDEX DNJSQO_T_IDX ON DNJSQO_T (C1);
--테스트를 위해서 SESSION LEVEL에서 cursor_sharing = FORCE 로 설정한다.
ALTER SESSION SET CURSOR_SHARING = FORCE;
--TRACE를 수행한다.
ALTER SESSION SET SQL_TRACE = TRUE;
--생성한 테이블에 아래와 같은 SQL을 각각 실행한다.
SELECT /* %% TEST */ *
FROM DNJSQO_T
WHERE C1 LIKE '%' || :1 || '%';
SELECT /* % TEST */ *
FROM DNJSQO_T
WHERE C1 LIKE :1 || '%';
/*
여기서 부터는 TRACE 결과임
두가지 SQL 모두 실행계획은 INDEX RANGE SCAN 이지만 읽은 블럭수를 확인해보면 전혀 다르다.
양쪽 '%' 로 조회한 SQL은 INDEX 32블럭(아마도 INDEX FULL SCAN) 을 읽어서 한 건을 찾고 테이블 엑세스를 하였으나,
우측 '%' 로 조회한 SQL은 INDEX 2블럭을 읽어서 한 건을 찾고 테이블을 엑세스 하였다.
이러한 현상이 발생하는 이유는 cursor_sharing 기능으로 SQL에 포함된 상수마저 변수 처리를 함으로써 해당 변수에 어떤 값이 대입될지 알 수 없으므로
발생하는 문제로 생각됨
*/
SELECT /* %% TEST */ *
FROM DNJSQO_T
WHERE C1 LIKE :"SYS_B_0" || :1 || :"SYS_B_1"
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.02 0.02 0 33 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.02 0.02 0 33 0 1
Misses in library cache during parse: 1
Optimizer mode: FIRST_ROWS
Parsing user id: 36
Rows Row Source Operation
------- ---------------------------------------------------
1 TABLE ACCESS BY INDEX ROWID DNJSQO_T (cr=33 pr=0 pw=0 time=20430 us)
1 INDEX RANGE SCAN DNJSQO_T_IDX (cr=32 pr=0 pw=0 time=20407 us)(object id 60949)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 1 0.00 0.00
SQL*Net message from client 1 0.00 0.00
********************************************************************************
SELECT /* % TEST */ *
FROM DNJSQO_T
WHERE C1 LIKE :1 || :"SYS_B_0"
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.00 0.00 0 3 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.00 0 3 0 1
Misses in library cache during parse: 1
Optimizer mode: FIRST_ROWS
Parsing user id: 36
Rows Row Source Operation
------- ---------------------------------------------------
1 TABLE ACCESS BY INDEX ROWID DNJSQO_T (cr=3 pr=0 pw=0 time=78 us)
1 INDEX RANGE SCAN DNJSQO_T_IDX (cr=2 pr=0 pw=0 time=50 us)(object id 60949)
댓글 없음:
댓글 쓰기