이번 칼럼은 11g에서 새롭게 소개된 SPM(SQL PLAN MANAGEMENT) 사용 방법 사용 방법에 대해 알아보고자 합니다.
SPM(SQL PLAN MANAGEMENT) 이란?
SPM은 baseline(Plan과 Hint)를 DB내에 저장 해 놓고 검증된 실행계획만 사용할 수 있도록 하는 기능이며, 통계정보 변경이나 application의 수정, DB version upgrade 등으로부터의 영향을 최소화 하는데 그 목적이 있습니다. SQL_PROFILE은 한 Category의 특정 SQL에 대해 오직 하나의 Plan만 저장할 수 있기 때문에, 다른 Plan을 적용시키기 위해서는 Category를 변경하여 저장하거나 새로운 Plan을 Stored Outline으로 저장해야 합니다. 하지만 SPM은 특정 SQL에 여러개의 Plan을 관리할 수 있으며, 그 중 필요한 Plan을 사용할 수 있기 때문에 보다 공격적인 Plan Fix 방법론이라 할 수 있습니다.
SQL PLAN MANAGEMENT | SQL PROFLIE |
*. Execution Plan의 변경으로 발생될지 모르는 성능저하를 예방하기 위한 사전 예방적인 방식이다.(Preventative Mechanism)
*. Plan Hit가 저장되고 Plan History가 관리된다. *. 저장된 Plan Hit대로 수행되므로 외부적인 환경변화가 있더라도 Plan은 변경되지 않는다. *. SQL Plan의 이력 관리가 됨. *. SQL Baseline에 검증된 Plan이 여러 개 존재할 수 있고 실행계획은 그 중에서 선택되어진다. *. Plan을 검증하는 기능이 있어 기존의 Plan대비 어느 정도의 Cost와 성능 향상이 기대되는지를 분석할 수 있다. 따라서 분석 결과에 따라 특정 Plan을 버릴 수도 있고 Plan으로 채택되지 않게 설정을 변경할 수도 있다. |
*. High-Loaded SQL의 Plan을 Tuning 한 결과로 생성되므로 사후 조치적인 방식이다.(Reactive Mechanism).
*. SQL이 잘 수행될 수 있도록 일반적인 통계정보 이외의 부가 정보를 Dictionary에 저장한다. Plan Hit가 저장되지 않음. *. SQL Profile이 생성되어 있더라도 외부적인 환경변화로 인해 SQL Plan이 변경될 수 있다. *. SQL Plan의 이력관리가 안 됨. *. 한 Category의 특정 SQL에 대해 오직 하나의 Plan만 저장할 수 있기 때문에 다른 Plan을 적응시키기 위해서는 Category를 변경하여 저장하거나 새로운 Plan을 Stored Outline으로 저장해야 한다 |
SPM 사용 예제
1 2 3 4 5 6 |
SELECT * FROM V$VERSION; BANNER ----------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production PL/SQL Release 11.2.0.3.0 - Production |
2. 테스트 테이블, 인덱스, 통계정보 생성
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
CREATE TABLE EMP (EMPNO NUMBER(4) NOT NULL, ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4), HIREDATE DATE, SAL NUMBER(7, 2), COMM NUMBER(7, 2), DEPTNO NUMBER(2)); INSERT INTO EMP VALUES (7369, 'SMITH', 'CLERK', 7902, TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20); INSERT INTO EMP VALUES (7499, 'ALLEN', 'SALESMAN', 7698, TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30); INSERT INTO EMP VALUES (7521, 'WARD', 'SALESMAN', 7698, TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30); INSERT INTO EMP VALUES (7566, 'JONES', 'MANAGER', 7839, TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20); INSERT INTO EMP VALUES (7654, 'MARTIN', 'SALESMAN', 7698, TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30); INSERT INTO EMP VALUES (7698, 'BLAKE', 'MANAGER', 7839, TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30); INSERT INTO EMP VALUES (7782, 'CLARK', 'MANAGER', 7839, TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10); INSERT INTO EMP VALUES (7788, 'SCOTT', 'ANALYST', 7566, TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20); INSERT INTO EMP VALUES (7839, 'KING', 'PRESIDENT', NULL, TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10); INSERT INTO EMP VALUES (7844, 'TURNER', 'SALESMAN', 7698, TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, 0, 30); INSERT INTO EMP VALUES (7876, 'ADAMS', 'CLERK', 7788, TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20); INSERT INTO EMP VALUES (7900, 'JAMES', 'CLERK', 7698, TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30); INSERT INTO EMP VALUES (7902, 'FORD', 'ANALYST', 7566, TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20); INSERT INTO EMP VALUES (7934, 'MILLER', 'CLERK', 7782, TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10); CREATE TABLE DEPT (DEPTNO NUMBER(2), DNAME VARCHAR2(14), LOC VARCHAR2(13) ); INSERT INTO DEPT VALUES (10, 'ACCOUNTING', 'NEW YORK'); INSERT INTO DEPT VALUES (20, 'RESEARCH', 'DALLAS'); INSERT INTO DEPT VALUES (30, 'SALES', 'CHICAGO'); INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON'); COMMIT; / CREATE UNIQUE INDEX EMP_U1 ON EMP (EMPNO); CREATE INDEX EMP_N1 ON EMP (DEPTNO); CREATE UNIQUE INDEX DEPT_U1 ON DEPT (DEPTNO); CREATE INDEX DEPT_N1 ON DEPT (LOC); BEGIN DBMS_STATS.GATHER_TABLE_STATS(USER, 'EMP', CASCADE => TRUE); END; / BEGIN DBMS_STATS.GATHER_TABLE_STATS(USER, 'DEPT', CASCADE => TRUE); END; / |
테스트로 많이 사용되는 EMP, DEPT 테이블을 생성하고, 통계정보를 만들었습니다.
3. Format 세팅
1 2 3 4 5 6 7 8 9 10 11 12 |
SET LINESIZE 200 PAGESIZE 1000 ECHO ON FEEDBACK OFF TRIMSPOOL ON COL SQL_HANDLE FORMAT A20 COL PLAN_NAME FORMAT A30 COL ORIGIN FORMAT A12 COL OCO FORMAT 9999 COL LAST_MODIFIED FORMAT A17 COL LAST_EXECUTED FORMAT A17 COL LAST_VERIFIED FORMAT A17 COL REPRODUCED FORMAT A3 COL SQL_TEXT FORMAT A65 COL PLAN_TABLE_OUTPUT FORMAT A130 ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YY/MM/DD HH24:MI:SS'; |
SQL-PLUS에서 테스트를 진행하기 때문에 출력 포멧을 지정합니다.
4. 테스트 DB에서 SQL_PLAN_BASELINES 파라미터 확인
1 2 3 4 |
NAME TYPE VALUE ------------------------------------ ---------------------- ------------ optimizer_capture_sql_plan_baselines boolean FALSE optimizer_use_sql_plan_baselines boolean TRUE |
SPM에서 사용되는 2개 hidden parameters는 위와 같이 2개이며, 그 기능은 아래와 같습니다.
- optimizer_capture_sql_plan_baselines : SPB를 통해 실행계획을 자동으로 캡쳐하도록 활성화하는 파라미터
- optimizer_use_sql_plan_baselines : SPB를 사용토록 활성화하는 파라미터
5. 세션 레벨에서 SPB 관련 파라미터 값 변경
1 2 |
ALTER SESSION SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES = TRUE; ALTER SESSION SET OPTIMIZER_USE_SQL_PLAN_BASELINES = FALSE; |
여기서 자동 캡쳐 기능을 테스트하기 위해 OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES 값을 TRUE로 변경하겠습니다.
6. SQL을 직접 수행하여 SPB 등록
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ=300; SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 ; MAX(EMPNO) COUNT(EMPNO) ---------- ------------ 0 1 row selected. Elapsed: 00:00:00.06 Execution Plan ---------------------------------------------------------- Plan hash value: 1849991560 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 | 5 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 7 | | | |* 2 | TABLE ACCESS FULL| EMP | 1 | 7 | 5 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("DEPTNO"=97) ; SET AUTOT OFF |
DEPT 테이블에 DEPTNO 컬럼으로 구성된 인덱스가 있어서 INDEX RANGE SCAN 실행계획이 나오겠지만, FULL SCAN을 유도하기 위해 세션레벨로 OPTIMIZER_INDEX_COST_ADJ 파라미터값을 변경해 보겠습니다. 이 파라미터는 값이 높을수록 FULL SCAN을 선호하고, 낮을수록 인덱스 사용을 선호합니다.
참고로 SPM은 1회 수행된 SQL은 SPB에 캡쳐가 안되고, 2회 이상부터 캡쳐가 됩니다.
7. 동일 SQL 재수행
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 ; SET AUTOT OFF SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, --LAST_MODIFIED, --LAST_EXECUTED, --LAST_VERIFIED, SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- ------------------- AUTO-CAPTURE YES YES NO 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 |
한번 더 수행하고 DBA_SQL_PLAN_BASELINES 뷰에서 SPM을 확인한 결과 해당 SQL이 등록된 걸 확인할 수 있으며, 그 의미는 아래와 같습니다.
- SQL_HANDLE : SQL_ID에 대한 SPB 대표이름
- PLAN_NAME : SQL_HANDLE에 종속된 Plan 이름
- ORIGIN : SPB 등록 방식(AUTO-CAPTURE 또는 MANUAL)
- ACCEPT : PLAN_NAME 중 ACCEPT가 YES인 경우에만 SPB로 사용됨
- FIXED : SQL_HANDLE 내에 여러 PLAN_NAME이 있을 경우 FIXED가 YES인 PLAN_NAME만 사용됨
TABLE FULL SCAN 실행계획이 등록되어 있으므로, 이제는 INDEX RANGE SCAN 실행계획을 등록해 보겠습니다. 동일한 방법으로 OPTIMIZER_INDEX_COST_ADJ 파라미터 값을 300에서 1로 다시 설정해서 인덱스를 사용하도록 유도합니다. 참고로 OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES, OPTIMIZER_USE_SQL_PLAN_BASELINES 2개 파라미터 중 하나라도 TURE일 경우 새로운 PLAN_NAME 등록됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ=1; SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97; SET AUTOT OFF MAX(EMPNO) COUNT(EMPNO) ---------- ------------ 0 Elapsed: 00:00:00.10 Execution Plan ---------------------------------------------------------- Plan hash value: 2854672349 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 | 1 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 7 | | | | 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 7 | 1 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | EMP_N1 | 1 | | 1 (0)| 00:00:01 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("DEPTNO"=97) ; |
9. SPB 확인
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, -- LAST_MODIFIED, -- LAST_EXECUTED, -- LAST_VERIFIED SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt59995a0e9 ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- ------------------- AUTO-CAPTURE YES NO NO 1 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- ------------------- AUTO-CAPTURE YES YES NO 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 |
SQL_TEXT로 확인한 결과, SQL_5009a0e70c6d5325 SQL_HANDLE 값이 동일한것이 2개 있고, SQL_PLAN_502d0ww66unt59995a0e9 값이 서로 다른 PLAN_NAME이 등록되었습니다.
10. XPLAN으로 SPB 확인
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
SELECT T.* FROM (SELECT DISTINCT SQL_HANDLE FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%') PB, TABLE(DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE(PB.SQL_HANDLE, NULL, 'TYPICAL')) T ; -------------------------------------------------------------------------------- SQL handle: SQL_5009a0e70c6d5325 SQL text: SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- Plan name: SQL_PLAN_502d0ww66unt59995a0e9 Plan id: 2576720105 Enabled: YES Fixed: NO Accepted: NO Origin: AUTO-CAPTURE -------------------------------------------------------------------------------- Plan hash value: 2854672349 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 | 1 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 7 | | | | 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 7 | 1 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | EMP_N1 | 1 | | 1 (0)| 00:00:01 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("DEPTNO"=97) -------------------------------------------------------------------------------- Plan name: SQL_PLAN_502d0ww66unt5c392520a Plan id: 3281146378 Enabled: YES Fixed: NO Accepted: YES Origin: AUTO-CAPTURE -------------------------------------------------------------------------------- Plan hash value: 1849991560 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 | 5 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 7 | | | |* 2 | TABLE ACCESS FULL| EMP | 1 | 7 | 5 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("DEPTNO"=97) |
XPLAN에서도 확인해보면, 더욱 확실히 알 수 있는데, SQL_PLAN_502d0ww66unt59995a0e9 값은 INDEX SCAN 플랜이고, SQL_PLAN_502d0ww66unt5c392520a 값은 FULL SCAN 플랜입니다.
11. 새로운 PLAN_NAME은 등록되나, 기존에 등록된 PLAN_NAME과 실행계획 동일할 경우 재 등록되지 않음
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ=300; SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97; SET AUTOT OFF SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, -- LAST_MODIFIED, -- LAST_EXECUTED, -- LAST_VERIFIED SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt59995a0e9 ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- ------------------- AUTO-CAPTURE YES NO NO 1 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- ------------------- AUTO-CAPTURE YES YES NO 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 |
12. ACCEPT PLAN_NAME 사용 확인
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
ALTER SESSION SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES = FALSE; ALTER SESSION SET OPTIMIZER_USE_SQL_PLAN_BASELINES = TRUE; ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ=1; SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97; SET AUTOT OFF Execution Plan ---------------------------------------------------------- Plan hash value: 1849991560 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 | 5 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 7 | | | |* 2 | TABLE ACCESS FULL| EMP | 1 | 7 | 5 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("DEPTNO"=97) Note ----- - SQL plan baseline "SQL_PLAN_502d0ww66unt5c392520a" used for this statement ; SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, -- LAST_MODIFIED, -- LAST_EXECUTED, -- LAST_VERIFIED SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt59995a0e9 ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- ------------------- AUTO-CAPTURE YES NO NO 1 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- ------------------- AUTO-CAPTURE YES YES NO 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 ; |
이제 SPM이 잘 작동하는지 확인해 보기 위해, OPTIMIZER_INDEX_COST_ADJ 값을 1로 주어 인덱스를 사용하는지 살펴본 결과 SQL_PLAN_502d0ww66unt5c392520a PLAN_NAME의 ACCEPT 값이 YES이기 때문에 FULL SCAN을 하는 것을 알 수 있으며, 잘 작동하는지 알 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
SET SERVEROUTPUT ON LONG 10000 DECLARE REPORT CLOB; BEGIN REPORT := DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(SQL_HANDLE => 'SQL_5009a0e70c6d5325'); DBMS_OUTPUT.PUT_LINE(REPORT); END; / ------------------------------------------------------------------------------- Evolve SQL Plan Baseline Report ------------------------------------------------------------------------------- Inputs: ------- SQL_HANDLE = SQL_5009a0e70c6d5325 PLAN_NAME = TIME_LIMIT = DBMS_SPM.AUTO_LIMIT VERIFY = YES COMMIT = YES Plan: SQL_PLAN_502d0ww66unt59995a0e9 ------------------------------------ Plan was verified: Time used .116 seconds. Plan passed performance criterion: 14 times better than baseline plan. Plan was changed to an accepted plan. Baseline Plan Test Plan Stats Ratio ------------- --------- ----------- Execution Status: COMPLETE COMPLETE Rows Processed: 1 1 Elapsed Time(ms): .074 .05 1.48 CPU Time(ms): 0 0 Buffer Gets: 14 1 14 Physical Read Requests: 0 0 Physical Write Requests: 0 0 Physical Read Bytes: 0 0 Physical Write Bytes: 0 0 Executions: 1 1 ----------------------------------------------------------------------------- -- Report Summary ------------------------------------------------------------------------ ------- Number of plans verified: 1 Number of plans accepted: 1 ; SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, -- LAST_MODIFIED, -- LAST_EXECUTED, -- LAST_VERIFIED SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt59995a0e9 ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- -------------------- AUTO-CAPTURE YES YES NO 1 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- -------------------- AUTO-CAPTURE YES YES NO 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ=1; SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97; SET AUTOT OFF Execution Plan ---------------------------------------------------------- Plan hash value: 2854672349 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 | 1 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 7 | | | | 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 7 | 1 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | EMP_N1 | 1 | | 1 (0)| 00:00:01 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("DEPTNO"=97) Note ----- - SQL plan baseline "SQL_PLAN_502d0ww66unt59995a0e9" used for this statement ; ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ=300; SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97; SET AUTOT OFF Execution Plan ---------------------------------------------------------- Plan hash value: 1849991560 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 | 5 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 7 | | | |* 2 | TABLE ACCESS FULL| EMP | 1 | 7 | 5 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("DEPTNO"=97) Note ----- - SQL plan baseline "SQL_PLAN_502d0ww66unt5c392520a" used for this statement |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
VAR PBSTS VARCHAR2(30); EXEC :PBSTS := DBMS_SPM.ALTER_SQL_PLAN_BASELINE('SQL_5009a0e70c6d5325', 'SQL_PLAN_502d0ww66unt5c392520a', 'FIXED', 'YES'); SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, -- LAST_MODIFIED, -- LAST_EXECUTED, -- LAST_VERIFIED SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt59995a0e9 ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- -------------------- AUTO-CAPTURE YES YES NO 1 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- -------------------- AUTO-CAPTURE YES YES YES 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ = 1; SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97; SET AUTOT OFF Execution Plan ---------------------------------------------------------- Plan hash value: 1849991560 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 | 5 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 7 | | | |* 2 | TABLE ACCESS FULL| EMP | 1 | 7 | 5 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("DEPTNO"=97) Note ----- - SQL plan baseline "SQL_PLAN_502d0ww66unt5c392520a" used for this statement |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
VAR PBSTS VARCHAR2(30); EXEC :PBSTS := DBMS_SPM.ALTER_SQL_PLAN_BASELINE('SQL_5009a0e70c6d5325', 'SQL_PLAN_502d0ww66unt59995a0e9', 'FIXED', 'YES'); SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, -- LAST_MODIFIED, -- LAST_EXECUTED, -- LAST_VERIFIED SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt59995a0e9 ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- -------------------- AUTO-CAPTURE YES YES YES 1 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- -------------------- AUTO-CAPTURE YES YES YES 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ = 1; SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97; SET AUTOT OFF Execution Plan ---------------------------------------------------------- Plan hash value: 2854672349 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 | 1 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 7 | | | | 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 7 | 1 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | EMP_N1 | 1 | | 1 (0)| 00:00:01 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("DEPTNO"=97) Note ----- - SQL plan baseline "SQL_PLAN_502d0ww66unt59995a0e9" used for this statement |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
var v_num NUMBER EXEC :V_NUM := DBMS_SPM.DROP_SQL_PLAN_BASELINE(SQL_HANDLE=>'SQL_5009a0e70c6d5325', PLAN_NAME=>'SQL_PLAN_502d0ww66unt59995a0e9'); SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, -- LAST_MODIFIED, -- LAST_EXECUTED, -- LAST_VERIFIED SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- -------------------- AUTO-CAPTURE YES YES YES 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 ALTER SESSION SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES = TRUE; ALTER SESSION SET OPTIMIZER_USE_SQL_PLAN_BASELINES = TRUE; ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ = 1; SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97; SET AUTOT OFF Execution Plan ---------------------------------------------------------- Plan hash value: 1849991560 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 | 5 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 7 | | | |* 2 | TABLE ACCESS FULL| EMP | 1 | 7 | 5 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("DEPTNO"=97) Note ----- - SQL plan baseline "SQL_PLAN_502d0ww66unt5c392520a" used for this statement ; SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, -- LAST_MODIFIED, -- LAST_EXECUTED, -- LAST_VERIFIED SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- -------------------- AUTO-CAPTURE YES YES YES 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 ; |
18. AUTO-CAPTURE가 아닌 MANUAL로 SPB 등록
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
ALTER SESSION SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES = FALSE; ALTER SESSION SET OPTIMIZER_USE_SQL_PLAN_BASELINES = FALSE; SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97; SET AUTOT OFF ; Execution Plan ---------------------------------------------------------- Plan hash value: 2854672349 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 | 2 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 7 | | | | 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 7 | 2 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | EMP_N1 | 1 | | 1 (0)| 00:00:01 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("DEPTNO"=97) ; SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE FROM V$SQL WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_ID CHILD_NUMBER PLAN_HASH_VALUE -------------------------- ------------ --------------- 5d3txdaq22gts 0 1849991560 5d3txdaq22gts 1 2854672349 --> Target 5d3txdaq22gts 2 1849991560 ; DECLARE MY_PLANS PLS_INTEGER; BEGIN MY_PLANS := DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE( SQL_ID => '5d3txdaq22gts', PLAN_HASH_VALUE => '2854672349', FIXED => 'NO', ENABLED => 'YES'); END; / SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, -- LAST_MODIFIED, -- LAST_EXECUTED, -- LAST_VERIFIED SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt59995a0e9 ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- -------------------- MANUAL-LOAD YES YES NO 1 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- -------------------- AUTO-CAPTURE YES YES YES 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 |
이번에는 AUTO-CAPTURE가 아닌 MANUAL로 SPB를 등록해 보겠습니다. MANUAL 등록 시, 해당 PLAN의 SQL_ID, PLAN_HASH_VALUE 값을 이용하여 MANUAL하게 SPB 등록할 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
ALTER SESSION SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES = TRUE; ALTER SESSION SET OPTIMIZER_USE_SQL_PLAN_BASELINES = TRUE; var v_num NUMBER EXEC :V_NUM := DBMS_SPM.DROP_SQL_PLAN_BASELINE(SQL_HANDLE=>'SQL_5009a0e70c6d5325', PLAN_NAME=>'SQL_PLAN_502d0ww66unt59995a0e9'); SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, -- LAST_MODIFIED, -- LAST_EXECUTED, -- LAST_VERIFIED SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- -------------------- AUTO-CAPTURE YES YES YES 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 ; VAR PBSTS VARCHAR2(30); EXEC :PBSTS := DBMS_SPM.ALTER_SQL_PLAN_BASELINE('SQL_5009a0e70c6d5325', 'SQL_PLAN_502d0ww66unt5c392520a', 'FIXED', 'NO'); ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ = 1; SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97; SET AUTOT OFF SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, -- LAST_MODIFIED, -- LAST_EXECUTED, -- LAST_VERIFIED SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt59995a0e9 ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- ------------------- AUTO-CAPTURE YES NO NO 1 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- -------------------- AUTO-CAPTURE YES YES NO 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 |
20. ACCEPT 값이 NO이고 FIXED만 YES일 경우 Plan이 선택되는지 확인
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
VAR PBSTS VARCHAR2(30); EXEC :PBSTS := DBMS_SPM.ALTER_SQL_PLAN_BASELINE('SQL_5009a0e70c6d5325', 'SQL_PLAN_502d0ww66unt59995a0e9', 'FIXED', 'YES'); SELECT SQL_HANDLE, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED, FIXED, OPTIMIZER_COST AS OCO, -- LAST_MODIFIED, -- LAST_EXECUTED, -- LAST_VERIFIED SQL_TEXT FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE 'SELECT MAX(EMPNO)%' ; SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt59995a0e9 ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- ------------------- AUTO-CAPTURE YES NO YES 1 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 SQL_HANDLE PLAN_NAME -------------------- ------------------------------ SQL_5009a0e70c6d5325 SQL_PLAN_502d0ww66unt5c392520a ORIGIN ENABLE ACCEPT FIXED OCO SQL_TEXT ------------ ------ ------ ------ ----- --------------------- AUTO-CAPTURE YES YES NO 5 SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97 ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ = 1; SET AUTOT ON EXPLAIN SELECT MAX(EMPNO), COUNT(EMPNO) FROM EMP WHERE DEPTNO = 97; SET AUTOT OFF Execution Plan ---------------------------------------------------------- Plan hash value: 1849991560 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 | 5 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 7 | | | |* 2 | TABLE ACCESS FULL| EMP | 1 | 7 | 5 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("DEPTNO"=97) Note ----- - SQL plan baseline "SQL_PLAN_502d0ww66unt5c392520a" used for this statement |
만약 ACCEPT 값이 NO이고 FIXED만 YES일 경우 어떤 Plan이 선택되는지 확인한 결과, FULL SCAN을 하는 SQL_PLAN_502d0ww66unt5c392520a 사용하는 것을 알 수 있으며 그 이유는, SQL_PLAN_502d0ww66unt59995a0e9 PLAN_NAME의 FIXED가 YES여도 ACCEPT값이 NO이기 때문에 선택이 되지 않는 걸 알 수 있습니다.
요약
1 2 3 4 5 6 7 8 9 10 11 12 |
1. OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES, OPTIMIZER_USE_SQL_PLAN_BASELINES 2개 파라미터 중 하나가 TRUE이면 New Plan 추가됨 2. SPM은 2번 이상 Shared Pool에 Hit 될 경우에만 등록됨 3. 같은 Plan은 SPM에 추가 등록되지 않음 4. DBA_SQL_PLAN_BASELINES 뷰에서 ACCEPT, FIXED 2가지 값에 의해 SPM 선택됨 - ACCEPT가 YES인 Plan만 선택됨 - 2개 이상 Plan이 YES일 경우 FIXED가 YES인 Plan만 선택됨 - FIXED가 YES여도 ACCEPT가 NO이면 Plan 선택 안됨 - APPEPT, FIXED 양쪽 모두 YES일 경우, 옵타마이저 Cost에 의해 플랜 선택됨 |
SPM 명령어 모음
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
-- 1. DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(RETUEN : CLOB) - 기능 : SPM에 등록된 PLAN 비교하여 더 나은 PLAN을 ACCEPT 하는 펑션 - 사용 샘플 DECLARE REPORT CLOB; BEGIN REPORT := DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(SQL_HANDLE => 'SQL_5009a0e70c6d5325'); DBMS_OUTPUT.PUT_LINE(REPORT); END; / -- 2. DBMS_SPM.ALTER_SQL_PLAN_BASELINE(RETURN : PLS_INTEGER) - 기능 : SPM에 등록된 PLAN 중, 더 나은 PLAN을 Fix하는 펑션 - 사용 샘플 VAR PBSTS VARCHAR2(30); EXEC :PBSTS := DBMS_SPM.ALTER_SQL_PLAN_BASELINE('SQL_5009a0e70c6d5325', 'SQL_PLAN_502d0ww66unt5c392520a', 'FIXED', 'YES'); -- 3. DBMS_SPM.DROP_SQL_PLAN_BASELINE(RETURN : PLS_INTEGER) - 기능 : SPM에 등록된 PLAN 중, 삭제하고자 하는 PLAN 선정하는 펑션 - 사용 샘플 var v_num NUMBER EXEC :V_NUM := DBMS_SPM.DROP_SQL_PLAN_BASELINE(SQL_HANDLE=>'SQL_5009a0e70c6d5325', PLAN_NAME=>'SQL_PLAN_502d0ww66unt59995a0e9'); -- 4. DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(RETURN : PLS_INTEGER) - 기능 : Shared pool에 등록된 SQL_ID를 SPM에 등록하는 펑션 - 사용 샘플 DECLARE MY_PLANS PLS_INTEGER; BEGIN MY_PLANS := DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE( SQL_ID => '5d3txdaq22gts', PLAN_HASH_VALUE => '2854672349', FIXED => 'NO', ENABLED => 'YES'); END; / |
Reference List
- Oracle Document
- http://wiki.gurubee.net/display/CORE/3.+SQL+PLAN+MANAGEMENT
About the Author
● 경력 10년(현 LG전자 GERP DBA/Tuning 업무)
● 세미나 : 오라클 SQL 튜닝 방법의 이해, DBMS_XPLAN과 10046 Trace를 이용한 SQL문 튜닝, 개발자를 위한 어플리케이션튜닝 세미나
팀장님 좋은 정보 감사합니다ㅎㅎ