2. 반도의 흔한 Oracle Tuning 절차
Explain Plan
AutoTrace
SQL*Trace
실행계획 확인
수행 시 실제 작업량 측정
내부 수행 절차상
부하를 일으키는 단계 확인
문제
파악
Query 변경
Hint 사용
Index 조정
그래도
안되면 ?
반정규화
집계Table 생성
4. AutoTrace
얼추 모든 면에서 SQL*Trace보다 안 좋다고 하던데…
Orange에서도 그냥 확인이 가능하고
굳이 SQLPlus에서 할려면…
http://www.slideshare.net/seokjoonyun9/20150612-oracle-1 참조
5. SQL*Trace
얼추 강려크하긴 한데… 쪼메 귀찮은 작업이 많이 필요하다.
하지만 Orange Plan Tool에서는 편하게 확인이 가능
굳이 SQLPlus에서 할려면…
http://www.slideshare.net/seokjoonyun9/20150612-oracle-1 참조
Compile Time : 2015/07/09 13:31:22
Trace File : c:oraclediagrdbmsorclorcltraceorcl_ora_11048.trc
Trace Version : 11.2.0.1.0
********************************************************************************
SELECT * FROM SCOTT.EMP
WHERE DEPTNO = :"SYS_B_0"
Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.001 0 0 0 0
Fetch 1 0.000 0.000 0 3 0 0
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 3 0.000 0.001 0 3 0 0
Misses in library cache during parse : 1
Optimizer Goal : ALL_ROWS
Parsing user : SYS (ID=0)
Rows Row Source Operation
------- -----------------------------------------------------------------------
0 TABLE ACCESS FULL EMP (cr=3 pr=0 pw=0 time=0 us cost=2 size=190 card=5)
SCOTT.EMP
---------
Rows=14 Blocks=1
Empty_Blocks=0 Avg_Space=0
Chain_Count=0 Avg_Row_Length=38
Avg_Space_Freelist_Blocks=0 Freelist_Blocks=0
Sample_Size=14 Last_Analyzed='2015/06/14 13:48:32'
Partitioned='NO' Tablespace='SYSTEM'
Column Name Nullable Column Type Distinct Buckets
-------------------------------- -------- ------------------- ---------- ----------
EMPNO NUMBER(4) 14 1
ENAME VARCHAR2(10) 14 1
JOB VARCHAR2(9) 5 1
MGR NUMBER(4) 6 1
HIREDATE DATE 13 1
SAL NUMBER(7,2) 12 1
COMM NUMBER(7,2) 4 1
DEPTNO NUMBER(2) 3 1
INDEX
-----------------------------------------------------------------------------
EMP_DEPTNO : DEPTNO
Type='NORMAL', Uniq='NO', Distinct=3, Rows=14, Last_Analyzed='2015/06/18 17:13:25'
I_EMP_EMPNO : EMPNO
Type='NORMAL', Uniq='YES', Distinct=14, Rows=14, Last_Analyzed='2015/06/23 10:49:35'
I_EMP_EMPNO_ENAME : EMPNO,ENAME
Type='NORMAL', Uniq='NO', Distinct=14, Rows=14, Last_Analyzed='2015/06/23 10:48:23'
I_EMP_ENAME : ENAME
Type='NORMAL', Uniq='NO', Distinct=14, Rows=14, Last_Analyzed='2015/06/22 18:16:37'
EMP_SAL : SAL
Type='NORMAL', Uniq='NO', Distinct=12, Rows=14, Last_Analyzed='2015/06/18 17:34:45'
뽀나스로 스키마 정보까지
6. SQL*Trace
Compile Time : 2015/07/09 13:31:22
Trace File : c:oraclediagrdbmsorclorcltraceorcl_ora_11048.trc
Trace Version : 11.2.0.1.0
********************************************************************************
SELECT * FROM SCOTT.EMP
WHERE DEPTNO = :"SYS_B_0"
Call Count CPU Time Elapsed Time Disk Query Current Rows
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Parse 1 0.000 0.000 0 0 0 0
Execute 1 0.000 0.001 0 0 0 0
Fetch 1 0.000 0.000 0 3 0 0
------- ------ -------- ------------ ---------- ---------- ---------- ----------
Total 3 0.000 0.001 0 3 0 0
Misses in library cache during parse : 1
Optimizer Goal : ALL_ROWS
Parsing user : SYS (ID=0)
Rows Row Source Operation
------- -----------------------------------------------------------------------
0 TABLE ACCESS FULL EMP (cr=3 pr=0 pw=0 time=0 us cost=2 size=190 card=5)
Column Description
Call Parse : Cursor를 Parsing 하고
Execution Plan을 생성하는데 대한 통계
Execute : Cursor의 실행 단계에 대한 통계
Fetch : Record를 실제로 Fetch하는데 대한 통계
Count 수행 횟수
CPU CPU 사용 시간
Elapsed 수행 소요 시간 : CPU time + Wait Time
( = Response 시점 – Call 시점)
Disk Disk로부터 읽은 Block 수
Query Consistent Mode에서 읽은 Buffer Block 수
Current Current Mode에서 읽은 Buffer Block수
Rows 읽거나 갱신한 처리 건수
Column Description
cr Consistent Mode Block Read
pr Physical Disk Block Read
pw Physical Disk Block Write
time 소요시간 ( um : microsecond)
cost 현재 Step에서 야기된 cost
size 현재 Step에서의 data size
card cardinality
Trace File에서 각 항들의 의미
DML : Parse Call + Execute Call
SELECT : Parse Call + Execute Call + Fetch Call (1회 이상 : 전송 Record 수 / ArraySize)
8. v$sysstat
• v$sysstat : Instance 가동 후 현재까지 누적 통계치
• v$sesstat : 개별 세션별로 확인
• v$mystat : 현재 접속해 있는 본인 세션
SQL이 수행되는 동안 지속적으로 그 항목들에 대한 누적 통계치를 저장
• v$sysstat 활용 방안 (예시)
1. 변화량 기반 분석
특정 시점들의 v$sysstat 값들을 별도 Table로 저장 한 뒤
그 사이의 delta 값으로 분석
(자세한 설명은 생략. 왜 ? 그냥 AWR을 활용하면 되니깐)
2. Ratio 기반 분석
Database의 전반적인 Health Check Ratio 값들을 연산
9. Ratio 분석
• Buffer Nowait %
buffer Block을 읽으려 할 때 buffer busy waits 대기 없이 곧바로 읽기에 성공한 비율
SELECT ROUND(100*(1-BFWT/GETS),2) "Buffer Nowait %"
FROM
(SELECT SUM(COUNT) BFWT FROM V$WAITSTAT),
(SELECT VALUE GETS FROM V$SYSSTAT WHERE NAME = 'session logical reads')
10. Ratio 분석
• Redo Nowait %
Redo Log를 기록할 공간을 요청하지 않고 곧바로 Redo Entry를 기록한 비율
비율이 낮다면 Log Switching 이 느리거나 너무 자주 발생함을 의미
Redo Log File 크기를 늘리거나, 덜 바쁜 Disk로 옮겨야 한다.
SELECT ROUND(100*(1-RLSR/RENT),2) "Redo Nowait %"
FROM
(SELECT VALUE RLSR FROM V$SYSSTAT WHERE NAME = 'redo log space requests'),
(SELECT VALUE RENT FROM V$SYSSTAT WHERE NAME = 'redo entries')
11. Ratio 분석
• Buffer Hit %
Disk 읽기를 수반하지 않고 Buffer Cache에서 Block 찾기에 성공한 비율
SELECT ROUND(100*(1-(PHYR-PHYRD-NVL(PHYRDL,0))/GETS),2) "Buffer Hit %"
FROM
(SELECT VALUE PHYR FROM V$SYSSTAT WHERE NAME = 'physical reads'),
(SELECT VALUE PHYRD FROM V$SYSSTAT WHERE NAME = 'physical reads direct'),
(SELECT VALUE PHYRDL FROM V$SYSSTAT WHERE NAME = 'physical reads direct (lob)'),
(SELECT VALUE GETS FROM V$SYSSTAT WHERE NAME = 'session logical reads')
12. Ratio 분석
• Latch Hit %
Latch 경합 없이 첫 번째 시도에서 곧바로 Latch를 획득한 비율
SELECT ROUND(100*(1-SUM(MISSES)/SUM(GETS)),2) "Latch Hit %"
FROM V$LATCH
13. Ratio 분석
• Library Hit %
Library Cache에 이미 적재된 SQL Cursor를 찾아서 바로 Hit한 확률
Pin 히트율은 Execute단계와 관련이 있고,
Get 히트율은 Parse 단계와 관련이 있다.
SELECT ROUND(100 * SUM(PINHITS) / SUM(PINS) , 2) "Library Cache Pin Hit %",
ROUND(100 * SUM(GETHITS) / SUM(GETS) , 2) "Library Cache Get Hit %"
FROM V$LIBRARYCACHE
14. Ratio 분석
• Soft Parse %
Execution Plan이 Library Cache에서 찾아져 Hard Parsing을 하지 않고 SQL을 수행한 비율
이 비율이 낮다면 Bind Variable를 사용하도록 개선해야 한다.
SELECT ROUND(100 * (1 - HPRS / PRSE), 2) "Soft Parse %"
FROM
(SELECT VALUE HPRS FROM V$SYSSTAT WHERE NAME = 'parse count (hard)'),
(SELECT VALUE PRSE FROM V$SYSSTAT WHERE NAME = 'parse count (total)')
15. Ratio 분석
• Execute to Parse %
Parse Call 없이 바로 SQL을 수행한 비율
SELECT ROUND(100 * (1 - PRSE / EXE), 2) "Execute to Parse %"
FROM
(SELECT VALUE EXE FROM V$SYSSTAT WHERE NAME = 'execute count'),
(SELECT VALUE PRSE FROM V$SYSSTAT WHERE NAME = 'parse count (total)')
16. Ratio 분석
• Parse CPU to Parse Elapsed %
Parsing 총 시간 중 CPU time이 차지한 비율
이 값이 낮다면 Parsing 도중 Wait가 많이 발생했음을 의미
SELECT DECODE(PRSELA,
0, TO_NUMBER(NULL),
ROUND(PRSCPU / PRSELA * 100, 2)) "Parse CPU to Parse Elapsed %"
FROM
(SELECT VALUE PRSELA FROM V$SYSSTAT WHERE NAME = 'parse time elapsed'),
(SELECT VALUE PRSCPU FROM V$SYSSTAT WHERE NAME = 'parse time cpu')
17. Ratio 분석
• Non-Parse CPU %
SQL 수행하면서 사용한 전체 CPU time 중 Parsing 이외의 작업의 비율
이 비율이 낮다면 Parsing 부하를 줄이도록 개선해야 한다.
SELECT DECODE(TCPU,
0, TO_NUMBER(NULL),
ROUND(PRSCPU / TCPU * 100, 2)) "Non-Parse CPU %"
FROM
(SELECT VALUE TCPU FROM V$SYSSTAT WHERE NAME = 'CPU used by this session'),
(SELECT VALUE PRSCPU FROM V$SYSSTAT WHERE NAME = 'parse time cpu')
18. Ratio 분석
• In-memory Sort %
전체 Sort 중 In-memory Sort로 수행한 비율
SELECT DECODE((SRTM+SRTD),
0, TO_NUMBER(NULL),
ROUND(100 * SRTM / (SRTD + SRTM), 2)) "In-memory Sort %"
FROM
(SELECT VALUE SRTM FROM V$SYSSTAT WHERE NAME = 'sorts (memory)'),
(SELECT VALUE SRTD FROM V$SYSSTAT WHERE NAME = 'sorts (disk)')
19. Ratio 분석
• Memory Usage %
Shared Pool 내에서 현재 사용 중인 메모리 비율
SELECT ROUND(100 * (1 - SUM(DECODE(NAME, 'free memory', BYTES))
/ SUM(BYTES)), 2) "Memory Usage %"
FROM V$SGASTAT
WHERE POOL = 'shared pool'