본문 바로가기
OraclE

SPM(SQL PLAN MANAGEMENT)

by 타마마임팩트_쫀 2022. 6. 13.

 

-- SPM(SQL PLAN MANAGEMENT) 
-- SPM은 baseline를 DB내에 여러개의 Plan을 저장 해 놓고 검증된 실행계획만 사용할 수 있도록 하는 기능이다. 


-- --------------------------------------------------------------------
-- 기본 설정
-- --------------------------------------------------------------------
set linesize 150
col NAME_COL_PLUS_SHOW_PARAM for a40
col VALUE_COL_PLUS_SHOW_PARAM for a25
show parameter sql_plan


NAME_COL_PLUS_SHOW_PARAM                 TYPE        VALUE_COL_PLUS_SHOW_PARAM
---------------------------------------- ----------- -------------------------
optimizer_capture_sql_plan_baselines     boolean     FALSE
optimizer_use_sql_plan_baselines         boolean     TRUE

-- OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES => TRUE : 자동수집, FALSE : 수동 수집 , default FALSE
-- OPTIMIZER_USE_SQL_PLAN_BASELINES => BASELINE 등록 이후 SPM PLAN 이용 할지 여부 (TRUE : 사용) 




-- --------------------------------------------------------------------
-- test sql
-- --------------------------------------------------------------------
WITH RETRY AS (
    SELECT LMR.REQ_URL 
      FROM LST_MEMSYNC_RETRY LMR
         , LST_MEMSYNC_ERR LME
     WHERE LMR.TRAN_ID = LME.TRAN_ID
       AND PROC_STS_CD = 9500
       AND LMR.REQ_URL IN ( '/api/member/ext/join'         /* 회원가입 */
                          , '/api/member/ext/modify'       /* 회원수정 */
                          , '/api/member/ext/secede'       /* 회원탈퇴 */
                          , '/api/member/ext/integrate'    /* 회원통합 */
                          , '/api/member/ext/lastBuyInfo'  /* 최종구매일자 조회 */
                          )
       AND LMR.PROC_DT >= TO_DATE(TO_CHAR(SYSDATE - 1/24, 'YYYYMMDDHH24MISS'), 'YYYYMMDDHH24MISS')
)
SELECT * 
  FROM (
        SELECT COUNT(CASE WHEN REQ_URL = '/api/member/ext/join'        THEN 1 END) AS "1"   /* 회원가입 */
             , COUNT(CASE WHEN REQ_URL = '/api/member/ext/modify'      THEN 1 END) AS "2"  /* 회원수정 */
             , COUNT(CASE WHEN REQ_URL = '/api/member/ext/secede'      THEN 1 END) AS "3"  /* 회원탈퇴 */
             , COUNT(CASE WHEN REQ_URL = '/api/member/ext/integrate'   THEN 1 END) AS "4"  /* 회원휴면복구 */
             , COUNT(CASE WHEN REQ_URL = '/api/member/ext/lastBuyInfo' THEN 1 END) AS "5"  /* 회원휴면처리 */
             , COUNT(*) AS TOTAL_CNT
        FROM RETRY
  ) T
 WHERE T.TOTAL_CNT > 0;





-- --------------------------------------------------------------------
-- OLD plan 
-- --------------------------------------------------------------------

SQL_ID  1s1tfdnkncynj, child number 0
-------------------------------------
WITH RETRY AS (     SELECT LMR.REQ_URL       FROM LST_MEMSYNC_RETRY LMR
         , LST_MEMSYNC_ERR LME      WHERE LMR.TRAN_ID = LME.TRAN_ID
   AND PROC_STS_CD = 9500        AND LMR.REQ_URL IN (
'/api/member/ext/join'         /* 회원가입 */                           ,
'/api/member/ext/modify'       /* 회원수정 */                           ,
'/api/member/ext/secede'       /* 회원탈퇴 */                           ,
'/api/member/ext/integrate'    /* 회원통합 */                           ,
'/api/member/ext/lastBuyInfo'  /* 최종구매일자 조회 */
 )        AND LMR.PROC_DT >= TO_DATE(TO_CHAR(SYSDATE - 1/24,
'YYYYMMDDHH24MISS'), 'YYYYMMDDHH24MISS') ) SELECT *   FROM (
SELECT COUNT(CASE WHEN REQ_URL = '/api/member/ext/join'        THEN 1
END) AS "1"   /* 회원가입 */              , COUNT(CASE WHEN REQ_URL =
'/api/member/ext/modify'      THEN 1 END) AS "2"  /* 회원수정 */
  , COUNT(CASE WHEN REQ_URL = '/api/member/ext/s   '

Plan hash value: 1914046030

----------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                               | Name                   | Starts | A-Rows |   A-Time   | Buffers | Reads  |
----------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                        |                        |      1 |      0 |00:00:00.01 |       4 |      3 |
|   1 |  VIEW                                   |                        |      1 |      0 |00:00:00.01 |       4 |      3 |
|*  2 |   FILTER                                |                        |      1 |      0 |00:00:00.01 |       4 |      3 |
|   3 |    SORT AGGREGATE                       |                        |      1 |      1 |00:00:00.01 |       4 |      3 |
|   4 |     NESTED LOOPS                        |                        |      1 |      0 |00:00:00.01 |       4 |      3 |
|*  5 |      TABLE ACCESS BY INDEX ROWID BATCHED| LST_MEMSYNC_RETRY      |      1 |      0 |00:00:00.01 |       4 |      3 |
|*  6 |       INDEX RANGE SCAN                  | IX02_LST_MEMSYNC_RETRY |      1 |      0 |00:00:00.01 |       4 |      3 |
|*  7 |      INDEX RANGE SCAN                   | IDX_LST_MEMSYNC_ERR_01 |      0 |      0 |00:00:00.01 |       0 |      0 |
----------------------------------------------------------------------------------------------------------------------------

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

   2 - filter(COUNT(*)>0)
   5 - filter((TO_NUMBER("PROC_STS_CD")=9500 AND INTERNAL_FUNCTION("LMR"."REQ_URL")))
   6 - access("LMR"."PROC_DT">=TO_DATE(TO_CHAR(SYSDATE@!-.0416666666666666666666666666666666666667,'YYYYMMDDHH24MISS
              '),'YYYYMMDDHH24MISS') AND "LMR"."PROC_DT" IS NOT NULL)
   7 - access("LMR"."TRAN_ID"="LME"."TRAN_ID")







-- --------------------------------------------------------------------
-- 인덱스 확인
-- --------------------------------------------------------------------

===============================
====== INDEX COLUMN CHECK =====
===============================

OWNER        INDEX_NAME                   COLUMN_NAME                  PARTITIONED        MB TABLESPACE_NAME                STATUS   UNIQUENES GLO
------------ ---------------------------- ---------------------------- ------------ -------- ------------------------------ -------- --------- ---
LFMMEM       IX02_LST_MEMSYNC_RETRY       PROC_DT                      NO              3,122 TS_LFM_IDX                     VALID    NONUNIQUE YES
                                          REQ_FAIL_CNT

             IX03_LST_MEMSYNC_RETRY       PROC_DT                      NO              7,085 TS_LFM_IDX                     VALID    NONUNIQUE YES
                                          PROC_STS_CD
                                          REQ_URL

             IX_LST_MEMSYNC_RETRY_01      REQ_URL                      NO              8,330 TS_LFM_IDX                     VALID    NONUNIQUE YES
                                          PROC_STS_CD
                                          REQ_FAIL_CNT

             PK_LST_MEMSYNC_RETRY         TRAN_ID                      NO              7,213 TS_LFM_IDX                     VALID    UNIQUE    YES







-- --------------------------------------------------------------------
-- NEW plan 
-- --------------------------------------------------------------------

SQL_ID  1s1tfdnkncynj, child number 1
-------------------------------------
WITH RETRY AS (     SELECT LMR.REQ_URL       FROM LST_MEMSYNC_RETRY LMR
         , LST_MEMSYNC_ERR LME      WHERE LMR.TRAN_ID = LME.TRAN_ID
   AND PROC_STS_CD = 9500        AND LMR.REQ_URL IN (
'/api/member/ext/join'         /* 회원가입 */                           ,
'/api/member/ext/modify'       /* 회원수정 */                           ,
'/api/member/ext/secede'       /* 회원탈퇴 */                           ,
'/api/member/ext/integrate'    /* 회원통합 */                           ,
'/api/member/ext/lastBuyInfo'  /* 최종구매일자 조회 */
 )        AND LMR.PROC_DT >= TO_DATE(TO_CHAR(SYSDATE - 1/24,
'YYYYMMDDHH24MISS'), 'YYYYMMDDHH24MISS') ) SELECT *   FROM (
SELECT COUNT(CASE WHEN REQ_URL = '/api/member/ext/join'        THEN 1
END) AS "1"   /* 회원가입 */              , COUNT(CASE WHEN REQ_URL =
'/api/member/ext/modify'      THEN 1 END) AS "2"  /* 회원수정 */
  , COUNT(CASE WHEN REQ_URL = '/api/member/ext/s   '

Plan hash value: 1100111422

-------------------------------------------------------------------------------------------------------------------
| Id  | Operation                               | Name                   | Starts | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                        |                        |      1 |      0 |00:00:00.01 |       4 |
|   1 |  VIEW                                   |                        |      1 |      0 |00:00:00.01 |       4 |
|*  2 |   FILTER                                |                        |      1 |      0 |00:00:00.01 |       4 |
|   3 |    SORT AGGREGATE                       |                        |      1 |      1 |00:00:00.01 |       4 |
|   4 |     NESTED LOOPS                        |                        |      1 |      0 |00:00:00.01 |       4 |
|   5 |      TABLE ACCESS BY INDEX ROWID BATCHED| LST_MEMSYNC_RETRY      |      1 |      0 |00:00:00.01 |       4 |
|*  6 |       INDEX RANGE SCAN                  | IX03_LST_MEMSYNC_RETRY |      1 |      0 |00:00:00.01 |       4 |
|*  7 |      INDEX RANGE SCAN                   | IDX_LST_MEMSYNC_ERR_01 |      0 |      0 |00:00:00.01 |       0 |
-------------------------------------------------------------------------------------------------------------------

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

   2 - filter(COUNT(*)>0)
   6 - access("LMR"."PROC_DT">=TO_DATE(TO_CHAR(SYSDATE@!-.0416666666666666666666666666666666666667,'YYYYMMD
              DHH24MISS'),'YYYYMMDDHH24MISS') AND "LMR"."PROC_DT" IS NOT NULL)
       filter((TO_NUMBER("PROC_STS_CD")=9500 AND INTERNAL_FUNCTION("LMR"."REQ_URL")))
   7 - access("LMR"."TRAN_ID"="LME"."TRAN_ID")






-- --------------------------------------------------------------------
-- 이전 플랜으로 SPM 등록
-- --------------------------------------------------------------------

-- sql id와 Plan hash value를 알고 있을때 
SET SERVEROUTPUT ON
DECLARE
  l_plans_loaded  PLS_INTEGER;
BEGIN
  l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(
    sql_id => '1s1tfdnkncynj',
    plan_hash_value => 1914046030);
    
  DBMS_OUTPUT.put_line('Plans Loaded: ' || l_plans_loaded);
END;
/

Plans Loaded: 1

PL/SQL procedure successfully completed.





-- sql id만 알고 있을때
SET SERVEROUTPUT ON
DECLARE
  l_plans_loaded  PLS_INTEGER;
BEGIN
  l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(
    sql_id => '1s1tfdnkncynj');
    
  DBMS_OUTPUT.put_line('Plans Loaded: ' || l_plans_loaded);
END;
/




-- --------------------------------------------------------------------
-- 등록된 SPB 조회
-- --------------------------------------------------------------------
-- SQL_HANDLE : SQL_ID에 대한 SPB 대표이름
-- PLAN_NAME : SQL_HANDLE에 종속된 Plan 이름
-- ENABLED : YES 일때 옵티마이저가 사용 가능
-- ACCEPT : PLAN_NAME 중 ACCEPT가 YES인 경우에만 SPB로 사용됨
-- FIXED : SQL_HANDLE 내에 여러 PLAN_NAME이 있을 경우 FIXED가 YES인 PLAN_NAME만 사용됨

set linesize 150
col plan_name for a40
select sql_handle, plan_name, to_char(created, 'YYYY/MM/DD HH24:MI:SS') created, enabled, accepted, fixed 
from dba_sql_plan_baselines;

SQL_HANDLE                     PLAN_NAME                                CREATED             ENA ACC FIX
------------------------------ ---------------------------------------- ------------------- --- --- ---
SQL_1f1d24da6058d80a           SQL_PLAN_1y794v9h5jq0a26ff63a8           2022/06/09 13:46:24 YES NO  NO
SQL_1f1d24da6058d80a           SQL_PLAN_1y794v9h5jq0aa1311447           2022/06/09 13:45:46 YES YES NO




-- --------------------------------------------------------------------
-- 쿼리 재수행 후 이전 plan 사용 하는지 확인
-- --------------------------------------------------------------------

SQL_ID  1s1tfdnkncynj, child number 2
-------------------------------------
WITH RETRY AS (     SELECT LMR.REQ_URL       FROM LST_MEMSYNC_RETRY LMR
         , LST_MEMSYNC_ERR LME      WHERE LMR.TRAN_ID = LME.TRAN_ID
   AND PROC_STS_CD = 9500        AND LMR.REQ_URL IN (
'/api/member/ext/join'         /* 회원가입 */                           ,
'/api/member/ext/modify'       /* 회원수정 */                           ,
'/api/member/ext/secede'       /* 회원탈퇴 */                           ,
'/api/member/ext/integrate'    /* 회원통합 */                           ,
'/api/member/ext/lastBuyInfo'  /* 최종구매일자 조회 */
 )        AND LMR.PROC_DT >= TO_DATE(TO_CHAR(SYSDATE - 1/24,
'YYYYMMDDHH24MISS'), 'YYYYMMDDHH24MISS') ) SELECT *   FROM (
SELECT COUNT(CASE WHEN REQ_URL = '/api/member/ext/join'        THEN 1
END) AS "1"   /* 회원가입 */              , COUNT(CASE WHEN REQ_URL =
'/api/member/ext/modify'      THEN 1 END) AS "2"  /* 회원수정 */
  , COUNT(CASE WHEN REQ_URL = '/api/member/ext/s   '

Plan hash value: 1914046030

-------------------------------------------------------------------------------------------------------------------
| Id  | Operation                               | Name                   | Starts | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                        |                        |      1 |      0 |00:00:00.01 |       4 |
|   1 |  VIEW                                   |                        |      1 |      0 |00:00:00.01 |       4 |
|*  2 |   FILTER                                |                        |      1 |      0 |00:00:00.01 |       4 |
|   3 |    SORT AGGREGATE                       |                        |      1 |      1 |00:00:00.01 |       4 |
|   4 |     NESTED LOOPS                        |                        |      1 |      0 |00:00:00.01 |       4 |
|*  5 |      TABLE ACCESS BY INDEX ROWID BATCHED| LST_MEMSYNC_RETRY      |      1 |      0 |00:00:00.01 |       4 |
|*  6 |       INDEX RANGE SCAN                  | IX02_LST_MEMSYNC_RETRY |      1 |      0 |00:00:00.01 |       4 |
|*  7 |      INDEX RANGE SCAN                   | IDX_LST_MEMSYNC_ERR_01 |      0 |      0 |00:00:00.01 |       0 |
-------------------------------------------------------------------------------------------------------------------

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

   2 - filter(COUNT(*)>0)
   5 - filter((TO_NUMBER("PROC_STS_CD")=9500 AND INTERNAL_FUNCTION("LMR"."REQ_URL")))
   6 - access("LMR"."PROC_DT">=TO_DATE(TO_CHAR(SYSDATE@!-.0416666666666666666666666666666666666667,'YYYYMMD
              DHH24MISS'),'YYYYMMDDHH24MISS') AND "LMR"."PROC_DT" IS NOT NULL)
   7 - access("LMR"."TRAN_ID"="LME"."TRAN_ID")

Note
-----
   - SQL plan baseline SQL_PLAN_1y794v9h5jq0aa1311447 used for this statement


-- Note 부분에 SQL plan baseline 에서 SQL_PLAN_1y794v9h5jq0aa1311447 사용하고 있다고 표기







-- --------------------------------------------------------------------
-- SPM 삭제
-- --------------------------------------------------------------------

SET SERVEROUTPUT ON
DECLARE
  l_plans_dropped  PLS_INTEGER;
BEGIN
  l_plans_dropped := DBMS_SPM.drop_sql_plan_baseline (sql_handle => 'SQL_1f1d24da6058d80a');
  DBMS_OUTPUT.put_line('Plans Dropped: ' || l_plans_dropped);
END;
/

Plans Dropped: 2

PL/SQL procedure successfully completed.

 

 

'OraclE' 카테고리의 다른 글

sqlarea 쿼리 확인  (0) 2022.07.21
SPM - 튜닝된 SQL의 실행계획을 등록하고 적용 하는 방법  (0) 2022.06.13
OGG 동기화 테이블 추가  (0) 2022.04.04
active session history  (0) 2022.01.30
orange plan 테이블 생성  (0) 2022.01.30