19
WareValley http://www.WareValley.com WareValley Oracle 중소기업 DB관리자를 위한 데이터베이스 성능 최적화 및 품질 고도화 전문가 과정 #3 오렌지팀 윤석준 선임연구원

[2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

Embed Size (px)

Citation preview

Page 1: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

WareValleyhttp://www.WareValley.com

WareValley

Oracle중소기업 DB관리자를 위한 데이터베이스

성능 최적화 및 품질 고도화 전문가 과정 #3

오렌지팀 윤석준 선임연구원

Page 2: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

- 1일차 : Tuning 도구- D/B Tuning이 어려운 이유- Oracle D/B 구조- Tuning Tools : AutoTrace, SQL*Trace, V$SQLAREA

- 2일차 : SQL Tuning #1 : Optimizer- Rule-based Optimizer- Cost-based Optimizer- 통계정보, Histogram- Hint

- 3일차 : SQL Tuning #2 : Index, Join- Index- Join

- 4일차 : Server Tuning- Shared pool tuning- Data buffer cache tuning* NoSQL 소개

Page 3: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

INDEX 설계 시 주의사항

1. 조건에 만족하는 Data가 전체의 10% 내외일때 가장 이상적

2. 대용량 Data를 가진 Table에 적용

( 20 ~ 30만건 이상인 경우는 적극적 고려)

3. 분포도가 나쁘더라도 Fast Index Scan이 가능한 경우 효과적

4. 여러가지 Index 중 적합한 Index로 생성해야 함

5. Index가 생성되는 Tablespace와 물리적 크기에 대해 고려

(Extent, Block 크기)

Page 4: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

Single Column INDEX vs Composite Index

SELECT * FROM BIG_EMP WHERE DEPTNO = 10 AND JOB = 'CLERK';

CREATE INDEX I_BIG_EMP_DEPTNO ON BIG_EMP(DEPTNO);CREATE INDEX I_BIG_EMP_JOB ON BIG_EMP(JOB);

CREATE INDEX I_BIG_EMP_DEPTNO_JOB ON BIG_EMP(DEPTNO, JOB);

Page 5: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

Composite INDEX 선행 Column 결정 기준

1. WHERE 절에서 자주 검색될수록

2. 분포도가 좋을수록

3. Data가 적을수록

4. 범위검색 (BETWEEN, >, <, LIKE)로 검색되지 않을 수록

Page 6: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

Composite INDEX 선행 Column 결정 기준 (예제 )

CREATE INDEX I_BIG_EMP_DEPTNO_HIREDATEON BIG_EMP(DEPTNO, JOB, HIREDATE);

Call Count CPU Time Elapsed Time Disk Query Current Rows------- ------ -------- ------------ ---------- ---------- ---------- ----------Parse 1 0.000 0.000 0 0 0 0Execute 1 0.000 0.001 0 0 0 0Fetch 2 0.000 0.000 0 137 0 3------- ------ -------- ------------ ---------- ---------- ---------- ----------Total 4 0.000 0.001 0 137 0 3

Rows Row Source Operation------- -----------------------------------------------------------------------

3 SORT ORDER BY (cr=137 pr=0 pw=0 time=0 us cost=0 size=0 card=0)3 SORT GROUP BY (cr=137 pr=0 pw=0 time=2 us)

131 CONCATENATION (cr=137 pr=0 pw=0 time=390 us)53 TABLE ACCESS BY INDEX ROWID BIG_EMP (cr=55 pr=0 pw=0 time=208 us)53 INDEX RANGE SCAN I_BIG_EMP_DEPTNO_HIREDATE (cr=2 pr=0 pw=0 time=52 us)50 TABLE ACCESS BY INDEX ROWID BIG_EMP (cr=52 pr=0 pw=0 time=98 us)50 INDEX RANGE SCAN I_BIG_EMP_DEPTNO_HIREDATE (cr=2 pr=0 pw=0 time=49 us)28 TABLE ACCESS BY INDEX ROWID BIG_EMP (cr=30 pr=0 pw=0 time=27 us)28 INDEX RANGE SCAN I_BIG_EMP_DEPTNO_HIREDATE (cr=2 pr=0 pw=0 time=27 us)

Call Count CPU Time Elapsed Time Disk Query Current Rows------- ------ -------- ------------ ---------- ---------- ---------- ----------Parse 1 0.000 0.000 0 0 0 0Execute 1 0.000 0.003 0 15 0 0Fetch 2 0.016 0.057 118 8062 0 3------- ------ -------- ------------ ---------- ---------- ---------- ----------Total 4 0.016 0.060 118 8077 0 3

Rows Row Source Operation------- -----------------------------------------------------------------------

3 SORT ORDER BY (cr=8062 pr=118 pw=0 time=0 us cost=0 size=0 card=0)3 SORT GROUP BY (cr=8062 pr=118 pw=0 time=0 us)

131 TABLE ACCESS BY INDEX ROWID BIG_EMP (cr=8062 pr=118 pw=0 time=195 us)28281 INDEX RANGE SCAN I_BIG_EMP_DEPTNO_HIREDATE (cr=119 pr=118 pw=0 time=293037 us)

CREATE INDEX I_BIG_EMP_DEPTNO_HIREDATEON BIG_EMP(HIREDATE, DEPTNO, JOB);

SELECT DEPTNO, COUNT(*), SUM(SAL)FROM BIG_EMPWHERE HIREDATE BETWEEN '1983-01,01' AND '1984-12-31'AND DEPTNO IN ( 70, 80 , 90 )

GROUP BY DEPTNOORDER BY SUM(SAL) DESC;

Page 7: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

INDEX를 사용하지 못하는 경우

1. Column을 함수로 변경

(SQL문을 적절히 바꾸던가… 아니면 Function-based Index를 사용하던가)

2. 부정문으로 비교 (<>, !=, ^=, NOT =, NOT BETWEEN, NOT LIKE)

( NOT EXISTS (SELECT 1 FROM … WHERE … ) 로 대체 가능 )

3. IS NULL, IS NOT NULL로 비교

(Index에 NULL값은 없다. 즉 모든 값이 NOT NULL)

(IN NOT NULL 대신 > ‘ ’ 이런식의 존재하는 한 무조건 만족하는 조건으로 검색을 할 수 있다.)

4. LIKE 연산자에서 %(와일드카드)가 앞에 있는 경우

Page 8: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

Function-based INDEX

1. Oracle 8i 부터 지원

2. WHERE의 함수를 적용한 Column 자체를 INDEX로 생성

3. Cost-based Optimizer에서만 사용이 가능

SELECT * FROM BIG_EMP WHERE NVL(SAL,0) < 4000;

CREATE INDEX I_BIG_EMP_SAL ON BIG_EMP(SAL) CREATE INDEX I_BIG_EMP_NVL_SAL ON BIG_EMP(NVL(SAL,0))

Call Count CPU Time Elapsed Time Disk Query Current Rows------- ------ -------- ------------ ---------- ---------- ---------- ----------Parse 1 0.000 0.000 0 0 0 0Execute 1 0.000 0.000 0 0 0 0Fetch 225 0.016 0.018 0 408 0 22395------- ------ -------- ------------ ---------- ---------- ---------- ----------Total 227 0.016 0.019 0 408 0 22395

Rows Row Source Operation------- -----------------------------------------------------------------------

22395 TABLE ACCESS FULL BIG_EMP (cr=408 pr=0 pw=0 time=6177 uscost=52 size=52128 card=1448)

Call Count CPU Time Elapsed Time Disk Query Current Rows------- ------ -------- ------------ ---------- ---------- ---------- ----------Parse 1 0.000 0.000 0 0 0 0Execute 1 0.000 0.009 0 2 0 0Fetch 225 0.031 0.052 48 22098 0 22395------- ------ -------- ------------ ---------- ---------- ---------- ----------Total 227 0.031 0.061 48 22100 0 22395

Rows Row Source Operation------- -----------------------------------------------------------------------

22395 TABLE ACCESS BY INDEX ROWID BIG_EMP (cr=22098 pr=48 pw=0 time=73745 uscost=50 size=52128 card=1448)

22395 INDEX RANGE SCAN I_BIG_EMP_NVL_SAL (cr=273 pr=48 pw=0 time=51442 uscost=2 size=0 card=261)

Page 9: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

Full Table Scan의 성능을 개선시키기 위한 솔루션

1. DB_FILE_MULTIBLOCK_READ_COUNT = 128 block

(라고 설정은 되어 있으나 실제로는 80 ~ 90 정도 성능)

2. Parellel-Query-Option

(Server Processor 가 Parallel query processor들을 생성하여 동시에 읽음)

Page 10: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

INDEX 생성

CREATE INDEX 를 실행하면…

-> Index 구성 Column 들의 Data를 Sorting 하고, Min, Mid Max 값 계산

-> 최초 Extent 생성 : 첫번째 Block에 Root Block 생성하고 Mid값 저장

-> 다음 Block부터 Sorting 된 Data들 저장 (Leaf Block)

-> Leaf Block의 정보를 저장하고 있는 Block 생성 (Branch Block)

- 최초 생성되는 Leaf Block 들 : Level 1

-> 새로 Data가 추가되었는데 Leaf Block이 꽉 찬 경우 ?

-> 해당 Leaf Block에 중간값을 두고, 양쪽으로 새로운 Leaf Block을 생성 : Level 2

-> 이런 식으로 Depth (Level)이 깊어질 수록 성능이 안좋아진다.

Page 11: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

INDEX Balancing 분석

ANALYZE INDEX [index_name] VALIDATE STRUCTURE;

SELECT (DEL_LF_ROWS_LEN / LF_ROWS_LEN) * 100 AS BALANCINGFROM INDEX_STATS;

* INDEX_STATS

• INDEX 현재 구조 분석

• Block 수

• 삭제된 행의 길이

• INDEX DEPTH (HEIGHT)

Page 12: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

INDEX 재구성

ALTER INDEX [index_name] REBUILD [NOLOGGING]TABLESPACE [tablespace_name];

• Balancing이 20% 초과하면 성능 저하가 심하므로 재구성 하는게 좋음 (사후조치)

(그럼 사전조치는 ? 물리적 설계 : 빈번한 DML 고려)

• INDEX 삭제 후 재 생성

• On-Line rebuild 가능 (DBMS_REDEFINITION Package)

• Tablespace 위치 변경도 가능

Page 13: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

INDEX 합병 (B*Tree)

ANALYZE INDEX [index_name] COALESCE;

SELECT INDEX_NAME, LEAF_BLOCKSFROM USER_INDEXES;

SELECT NAME, BLOCKS, LF_BLKS, BR_BLKSFROM INDEX_STATS;

• INDEX Key 값을 재 배치

• 불필요한 Block 검색 및 공간 낭비를 방지

• 하지만 빈 Node를 반환해주지는 않음

Page 14: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

INDEX 압축 (B*Tree, IOT)

SELECT INDEX_NAME, COMPRESSIONFROM USER_INDEXES;

• 디스크 공간 절약I/O를 줄일 수 있으므로 검색속도 향상

(하지만 Transaction이 조금만 증가해도 느려질 수 있다)

• 대용량 Data에 적용하면 효율적

• Non-Partitioned Index에만 적용 가능

CREATE INDEX [index_name] ON [table_name]([column_name,...]) [ COMPRESS | NOCOMPRESS ];

Page 15: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

INDEX Monitoring

• INDEX는 SELECT의 성능을 올려주지만,

DML 들의 성능을 떨어트린다.

• Optimizer가 안 쓰는 INDEX는 과감히 삭제하자.

• 9i부터 가능

• 사용되지 않은 Index를 검색하여 삭제 가능

• Table 당 Index를 32개까지 생성은 가능하나,

Index가 많을 수록 DML문의 성능이 저하됨

ALTER INDEX [index_name] [ MONITORING | NOMONITORING ] USAGE;

SELECT INDEX_NAME, USEDFROM V$OBJECT_USAGE;

Page 16: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

INDEX 분석용 Script

SELECT X.TABLE_NAME, X.NUM_ROWS,A.INDEX_NAME, A.TABLESPACE_NAME,DECODE(A.UNIQUENESS, 'UNIQUE','U','N') "UNIQUE",B.COLUMN_NAME,Y.NUM_DISTINCT,A.PCT_FREE, A.CLUSTERING_FACTOR, A.BLEVEL, A.LEAF_BLOCKS,(C.DEL_LF_ROWS_LEN / C.LF_ROWS_LEN) * 100 BALANCE

FROM DBA_TABLES X, DBA_TAB_COLUMNS Y, DBA_INDEXES A, DBA_IND_COLUMNS B, INDEX_STATS CWHERE X.OWNER = 'SCOTT'AND A.TABLE_OWNER = X.OWNER AND A.TABLE_NAME = X.TABLE_NAMEAND A.TABLE_OWNER = B.INDEX_OWNER AND A.TABLE_NAME = B.TABLE_NAMEAND X.OWNER = Y.OWNER AND X.TABLE_NAME = Y.TABLE_NAMEAND B.COLUMN_NAME = Y.COLUMN_NAMEAND B.INDEX_NAME = C.NAME(+)ORDER BY X.TABLE_NAME

Page 17: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

Join 종류

Join description

Natural Join 결합조건이 = 인 일반적인 Join조건에 맞는 것만 출력( = Equal Join , Inner Join )

Cross Join 결합조건이 없는 Join전체와 전체를 다 묶음 (묻지마 Join)( = Catesian Product )

Self-reference Join 하나의 Table을 다른 Alias를 붙여서 Join(마치 다른 Table인 듯 취급)

Outer Join 기준이 되는 Table은 결합조건에 맞지 않아도 출력

1. 문법적 측면

Page 18: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

Join 종류

Join description

Sort-Merge Join/*+USE_MERGE(a b)*/

Join에 참여하는 Column에 Index가 없을 경우Full Table Scan -> 그 결과를 Sort한 후 Merge(즉 3번의 Load가 필요함)가장 느린 방법

Nested-Loops Join/*+USE_NL(a b)*/

Index를 이용하여 Join

Cluster Join Index보다 성능이 좋은 Cluster를 이용하여 Join

Hash Join/*+HASH(a b)*/

v7.3.3부터 가능 : SMJ가 넘 느려서 성능 개선을 위해 개발왠만해서는 SMJ보다 빠름Optimizer가 SMJ를 선택하는 경우는 거의 없다.결합조건 별로 Buffer에 파티션을 나누어 Record를 Load

2. 실행적 측면

Page 19: [2015-06-26] Oracle 성능 최적화 및 품질 고도화 3

Join 성능에 영향을 주는 요소

1. Driving Table

2. Join 순서

3. Data 량

4. Index 사용여부

WHERE 절의 Check 조건으로 걸러지는 것 기준으로

Data량이 가장 작은 것을 Driving Table로

Driving Table과 결합조건이 있는 Table중

Data량이 가장 작은 것을 Join

만약 결합 조건 중 한쪽만 Index가 있다면,

Join 할 Table을 Index가 있는 Table로 결정

Driving Table 결정 원리 (Rule-based Optimizer)

- Join에 참여하는 Column에 모두 INDEX가 있거나 없는 경우 (동등조건) : FROM에서 먼 쪽부터

-> 단, Single Index와 Composite Index 중에서는 Composite Index부터,

-> Unique Index와 Non-unique Index 중에서는 Unique Index 부터,

- Outer Join은 Data가 있는 쪽부터

- /*+ORDERED*/ 하면 FROM에서 가까운 쪽부터

- /*+LEADING(A)*/ 하면 해당 Table 부터