Oracle에서 성능 개선을 위해 실행계획을 사용한다.
아래와 같이 실행계획은 예상 실행계획과 실제 실행계획 방법을 살펴보자
예상 실행계획
Toad, Orange와 같은 Tool에서는 "ctrl+e" 눌러서 예상 실행계획을 편하게 확인하는 경우가 있으나 자세한 정보를 보기 위해서는 아래와 같이 따라한다.
SELECT * FROM T_ORD WHERE ORD_SEQ = 4;
위 쿼리를 예상 실행계획으로 실행하고 싶은 경우엔 아래와 같이 실행한다.
-- 실행계획 만들기
EXPLAIN PLAN FOR
SELECT * FROM T_ORD WHERE ORD_SEQ = 4;
-- 실행계획 확인하기
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
위와 같이 쿼리 2문장을 순서대로 각각 실행하면 아래와 같이 예상 실행계획 결과가 나온다.
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 44 | 2 (0)|
| 1 | TABLE ACCESS BY INDEX ROWID| T_ORD | 1 | 44 | 2 (0)|
|* 2 | INDEX UNIQUE SCAN | PK_T_ORD | 1 | | 1 (0)|
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ORD_SEQ"=4)
-- Id : 실행계획의 오퍼레이션 ID (구분자, 순서아님)
-- Operation : 해당 단계에 수행한 작업 내용
-- Name : 해당 단계에 작업을 수행한 대상 오브젝트(테이블 또는 인덱스)
-- Rows : 해당 단계 수행 시 조회될 예상 데이터 건수
-- Bytes : 해당 단계까지 사용될 예상 데이터양(누적)
-- Cost (%CPU) : 해당 단계까지 사용될 예상 비용(누적)
실제 실행계획
SELECT *
FROM T_ORD T1
, M_CUS T2
WHERE T1.CUS_ID = T2.CUS_ID
AND T1.ORD_DT >= TO_DATE('20170101','YYYYMMDD')
AND T1.ORD_DT < TO_DATE('20170201','YYYYMMDD')
AND T2.CUS_GD = 'A';
위 쿼리를 실제 실행계획으로 실행하고 싶은 경우엔 아래와 같이 실행한다.
1번 : 실제 실행계획 만들기(hint 추가)
SELECT /*+ GATHER_PLAN_STATISTICS */
*
FROM T_ORD T1
, M_CUS T2
WHERE T1.CUS_ID = T2.CUS_ID
AND T1.ORD_DT >= TO_DATE('20170101','YYYYMMDD')
AND T1.ORD_DT < TO_DATE('20170201','YYYYMMDD')
AND T2.CUS_GD = 'A';
2번 : 실제 실행계획을 만든 SQL의 SQL_ID찾아내기
SELECT T1.SQL_ID ,T1.CHILD_NUMBER ,T1.SQL_TEXT
FROM V$SQL T1
WHERE T1.SQL_TEXT LIKE '%GATHER_PLAN_STATISTICS%'
ORDER BY T1.LAST_ACTIVE_TIME DESC;
3번 : 실제 실행계획 조회하기(각자의 SQL_ID, CHILD_NUMBER를 사용할 것)
SELECT *
FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('3ykn80uy9n32d',0,'ALLSTATS LAST'));
위와 같이 1~3번 쿼리를 순서대로 실행하면 아래와 같이 실제 실행계획 결과가 나온다.
PLAN_TABLE_OUTPUT
SQL_ID 3ykn80uy9n32d, child number 0
-------------------------------------
SELECT /*+ GATHER_PLAN_STATISTICS */ * FROM T_ORD T1 ,
M_CUS T2 WHERE T1.CUS_ID = T2.CUS_ID AND T1.ORD_DT >=
TO_DATE('20170101','YYYYMMDD') AND T1.ORD_DT <
TO_DATE('20170201','YYYYMMDD') AND T2.CUS_GD = 'A'
Plan hash value: 3240201901
-----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 101 |00:00:00.01 | 12 | | | |
|* 1 | HASH JOIN | | 1 | 170 | 101 |00:00:00.01 | 12 | 779K| 779K| 1234K (0)|
|* 2 | TABLE ACCESS FULL| M_CUS | 1 | 60 | 60 |00:00:00.01 | 7 | | | |
|* 3 | TABLE ACCESS FULL| T_ORD | 1 | 252 | 146 |00:00:00.01 | 5 | | | |
-----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T1"."CUS_ID"="T2"."CUS_ID")
2 - filter("T2"."CUS_GD"='A')
3 - filter(("T1"."ORD_DT"<TO_DATE(' 2017-02-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"T1"."ORD_DT">=TO_DATE(' 2017-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss')))
-- Starts : 해당 단계를 수행한 횟수
-- E-Rows : 해당 단계의 예상 데이터 건수
-- A-Rows : 해당 단계의 실제 데이터 건수
-- A-Time : 해당 단계까지 수행된 실제 시간(누적)
-- Buffers : 해당 단계까지 메모리 버퍼에서 읽은 블록 수(논리적 IO 횟수, 누적)
-- Reads : 해당 단계까지 디스크에서 읽은 블록 수(물리적 IO 횟수, 누적)
-- OMem : SQL 처리를 위해 사용한 메모리 수치
-- 1Mem : SQL 처리를 위해 사용한 메모리 수치
-- Used-Mem : SQL 처리를 위해 사용한 메모리 수치
끝.
'DB > Oracle' 카테고리의 다른 글
Orange, Toad 에서 Parameter 확인 방법 (0) | 2022.04.13 |
---|---|
Oracle INDEX (0) | 2022.03.10 |
CONNECT BY LEVEL (0) | 2021.12.31 |
ORA-12899: value too large for column, 오라클 문자열 길이 구하기 (0) | 2021.12.14 |
TRUNC(값, 옵션) (0) | 2021.11.04 |