- 이 문서는 구루비에서 작성하였습니다.
- 이 문서를 다른 블로그나 홈페이지에 게재하실 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 출처 : http://wiki.gurubee.net/pages/viewpage.action?pageId=1966795&
- 구루비 지식창고의 모든 문서는 크리에이티브 커먼즈의 저작자표시-비영리-동일조건변경허락(BY-NC-SA) 라이선스에 따라 자유롭게 사용할 수 있습니다.
11. 데이터베이스 튜닝
1. 데이터베이스 설계 튜닝
데이터베이스 설계 단계에서 성능을 고려하여 설계
2. 데이터베이스 환경
성능을 고려하여 메모리나 블록 크기 등을 지정
3. SQL 문장 튜닝
성능을 고려하여 SQL 문장을 작성
1) 데이터베이스 튜닝의 목적
튜닝을 수행하는 이유는 물론 데이터베이스의 활용 성능을 최상/최적으로 만들기 위해서다.
(1) 업무적인 환경과 시스템적 환경에 적합한 데이터베이스 파라미터를설정한다.
(2) 데이터베이스에 접근하는 SQL 문장은 가능한 한 디스크 블록에 최소로 접근하도록 한다.
(3) 디스크 브록에서 한 번 읽은 데이터는 가능하면 메모리 영역에 보관한다.
(4) 모든 사용자의 SQL 문장은 공유 가능하도록 명명 표준을 준수하여 작성한다.
(5) 잠금 발생이 최소가 되도록 한다.
2) 데이터베이스 설계 단계에서 튜닝하기
- 데이터 정합성을 유지할 수 있는 대책을 마련하고, 성능을 위해 필요하다면 테이블,
컬럼, 관계에 대해 반정규화를 적용한다. - 대용량 테이블의 경우 필요한 데이터에 대해서는 파티셔닝을 이용하여 테이블 분할을
검토한다.
- 이력을 관리해야 하는 테이블에 대해서는 필요하다면 시작과 종료나 현재 상태 등을
명확하게 명시하여 SQL 문장의 실행 성능을 보장한다. - 테이블 접근 유형에 따라 전체 스캔 방식이나 B 트리 인덱스, 비트맵 인덱스,
클러스터링과 해싱 적용 등을 고려한다. - 테이블이 조회를 주로 하는지 입력,수정,삭제 작업이 주로 발생하는지를 고려하여
적당한 인덱스 개수를 지정해야 한다. 극단적으로 조회만 발생하는 경우에는 테이블에
인덱스가 많이 있어도 무방하지만, 입력, 수정, 삭제가 빈번한 테이블에서는 인덱스가
많으면 매번 인덱스를 수정해야 하므로 성능을 저하시키는 원인이 된다. - 분산 데이터베이스를 적용했을 경우 원격 테이데베이스를 이용할 때 성능 저하가
에상된다면 스냅샷을 이용한 복제 테이블 생성 등을 고려한다. - 공통적으로 관리하는 코드 데이터에 대한 접근이 빈번하다면 애플리케이션의 메모리에
상주시키고 함수를 사용하여 코드 변환을 하도록 유도한다. - PK는 일반적으로 지정된 순서대로 인덱스를 생성하므로 키를 구성하는 컬럼 순서를
복합 컬럼 인덱스를 지정하는 규칙에 따라 나열한다. - FK에 대해서는 가급적 인덱스를 생성하여 전체 스캔이 발생하는 경우와 불필요하게
발생하는 잠금을 피하도록 한다. - 복합 컬럼 인덱스를 지정하는 규칙은
첫째, 항상 조회 조건으로 사용하는 컬럼이 존재한다면 맨앞에 오게 한다.
기업의 업무에서는 일반적으로 사업소코드,지사코드,지점코드 또는 회사코드와
같이 지역을 나타내거나 데이터를 분리하는 단위를 첫째 컬럼으로 이용한다.
둘째는 WHERE 조건절에서 '='로 비교되는 컬럼이 있으면 앞쪽에 오게 한다.
섯째는 데이터의 분포도가 낮은 컬럼이 앞쪽에 오게 한다.
넷째는 정렬이 자주발생하는 컬럼이 앞쪽에 오게 한다. - SYSTEM 테이블 스페이스에는 데이터를 관리하는 딕셔너리 정보만 포함하고,
일반 오브젝트는 저장하지 않도록 한다.
![]() | [오라클 패치, Upgrade 정보] Oracle Version Upgrade 의 이유 - Optimizer Upgrade, New Feature, Maintenance Oracle Patch - DB Bug 수정 |
![]() | [SYSAUX Tablespace 정보]
이 tablespace는 다음과 같은 모든 Oracle option들과 기능들에 관한 Option or Feature Schema Tablespace in 8, 8i or 9i Oracle Label Security LBACSYS SYSTEM Recovery Catalog RMAN TOOLS Streams SYS (STREAM$_xxx) SYSTEM Statspack PERFSTAT User Specified Auditing SYS (AUD$) \ |
![]() | [파티션테이블 정보] FROM 엔코아 문 : 박범철 정성어린 답변에 미리 감사드립니다. ^^
파티션을 적용할 것이냐 말것이냐의 결정 기준은 파티션의 특징을 정확하게 이해하고 파티션이라는 것은 테이블을 수평분할한 것으로 어떠한 생성 규칙에 맞는 데이터들만 즉 내가 주로 처리하는 데이터 량이 일정량 이상이 되어 인덱스만 가지고는 효과를 보기 2. 대용량테이블에 대해서 반드시 파티션을 적용해야만 하는가? 대용량 테이블이라 하더라도 주로 ACCESS하는 데이터가 소량이고 OLTP성 처리가 3 ACCESS 패턴이 PREFIX INDEX 만으로 제한되지 않아서 NONPREFIX INDEX 가 상당수 존재하는 경우 4. 위의 경우는 테이블과 인덱스의 파티션키가 동일한 경우를 가정하였는데, 인덱스에는 PREFIX와 NON-PREFIX 두개가 있습니다. PREFIX형태의 조회조건이 들어오지 예를 들면 조회조건에 고객번호가 = 로 들어오는데 파티션은 고객번호를 선두로 하지 않은 이 경우 고객번호로 LOCAL NON-PREFIX INDEX를 만든 다음 PARTITION PRUNING 조건인 인덱스를 통해 ACCESS함에 모든 파티션에 있는 LOCAL INDEX를 ACCESS하게 됩니다만 |
3)데이터베이스 환경 튜닝
![]() | [오라클 성능 분석 방법론 정보] RATIO ANALYSIS - 성능 분석 방법론
|
공유 풀 튜닝
오라클의 공유 풀 영역은 라이브러리 캐시와 딕셔너리 캐시로 구분되며,
라이브러리 캐시에는 SQL 문장과 PL/SQL 문장이 저장되고, 딕셔너리 캐시에는
데이터베이스에 관련된 각종 정보들이 딕셔너리로 저장된다.
라이브러리 캐시 튜닝
HIT 율 ( 90% 보다 커야 한다. )
sys@ARTDOM>select gets, gethitratio, pins, pinhitratio, reloads, invalidations 2 from v$librarycache 3 where namespace ='SQL AREA'; GETS GETHITRATIO PINS PINHITRATIO RELOADS INVALIDATIONS ---------- ----------- ---------- ----------- ---------- ------------- 340751 .990635391 1383994 .995631484 756 1197
재파싱 율 ( 1% 보다 작게 나와야 한다. )
sys@ARTDOM>select (sum(reloads)/sum(pins))*100 "MISS RATE" 2 from v$librarycache ; MISS RATE ---------- .083522836
라이브러리 캐시의 HIT 율을 향상 시키는 방법
1. init<SID>.ora 파일에서 shared_pool_size 를 크게 한다.
2. 명명표준을 준수하여 동일한 문장에 대해 재파싱 작업이 일어나지 않게 한다.
3. 상수를 사용하기보다는 바인딩 변수를 사용한다.
딕셔너리 캐시튜닝
sys@ARTDOM> select to_char(trunc(sum(getmisses)/sum(gets)*100,5),0999.99)||'%(LESS THAN 15%)' "MISS RATE" from v$rowcache ; MISS RATE ----------------------- 4.05%(LESS THAN 15%)
리두로그 버퍼 튜닝
[VLDB: WAIT\_RATIO 가 1\% 이상이 나오면 리두로그가 발생할 때 경합이 발생한 경우다.]
리두로그 버퍼는 모든 SQL 문장이 실행될 때 이용하는 메모리 영역이므로 작업하는 동안은
이 메모리 공간을 이용해야 한다. 데이터에 대해 수정이 발생하면 잠금을 설정하듯이
메모리 영역에서 다른 프로세스가 이용하지 못하도록 독점하는 방법으로 래치(LATCH)를
할당받아 작업한다. 래치를 할당받지 못한 SQL 문장들은 래치를 할당받을 때까지 기다려야
한다. 그러므로 대기율을 분석하여 오랜 시간동안 대기하고 있거나 잦은 대기 상태가 되는
경우에는 리두 로그 버퍼의 크기를 조정해야 한다.
sys@ARTDOM>select a.name, (b.misses/b.gets)*100 WAIT_RATIO from v$latchname a, v$latch b where a.name in ('redo allocation') and a.latch# = b.latch# ; NAME WAIT_RATIO -------------------------------------------------- ---------- redo allocation .034880924 sys@ARTDOM>select name, value from v$sysstat where name ='redo log space requests'; NAME VALUE -------------------------------------------------- ---------- redo log space requests 57
디스크 I/O 튜닝
특정 디스크에 있는 데이터 파일에 I/O가 집중되면 이는 성능 저하의 요인이 되므로
I/O 현황을 분석하여 집중된 I/O를 분산시켜야 한다.
sys@ARTDOM> select name, phyrds, phywrts, phyblkrd, phyblkwrt from v$filestat, v$datafile where v$filestat.file# = v$datafile.file# ; NAME PHYRDS PHYWRTS PHYBLKRD PHYBLKWRT -------------------------------------------------- ---------- ---------- ---------- ---------- /u02b/ORACLE/ARTDOM/ARTDOM/system01.dbf 5381 18424 7194 19874 /u02b/ORACLE/ARTDOM/ARTDOM/undotbs01.dbf 47 11516 47 26253 /u02b/ORACLE/ARTDOM/ARTDOM/sysaux01.dbf 3212 19088 9979 26131 /u02b/ORACLE/ARTDOM/ARTDOM/DATA/users01.dbf 50 36 179 180 /u02b/ORACLE/ARTDOM/ARTDOM/example01.dbf 35 26 43 26 /u02b/ORACLE/ARTDOM/ARTDOM/DATA/users02.dbf 59 43 183 187 /u02b/ORACLE/ARTDOM/ARTDOM/DATA/users03.dbf 42 32 158 156 /u02b/ORACLE/ARTDOM/ARTDOM/DATA/users04.dbf 42 32 158 156 /u02b/ORACLE/ARTDOM/ARTDOM/DATA/users05.dbf 38 38 153 162 9 rows selected.
![]() | [v$filestat 정보] PHYRDS NUMBER Number of physical reads done |
일반적으로 데이터베이스의 디스크 I/O 를 줄이기 위해서는 다음과 같은 설계
방법을 권한다.
- 시스템 테이블 스페이스를 별도로 생성한다.
- 임시 테이블 스페이스는 테이블과 인덱스의 테이블 스페이스와 분리하여 생성한다.
- 롤백 세그먼트와 온라인 리두로그 파일은 분리하여 생성한다.
- 온라인 리두로그 파일과 아카이브 리두로그 파일은 분리하여 생성한다.
- 롤백 세그먼트와 테이블과 인덱스 테이블 스페이스와 분리하여 생성한다.
- 테이블의 테이블 스페이스와 인덱스의 테이블 스페이스는 분리하여 생성한다.
- 리두로그 파일은 지속적으로 I/O 가 발생하므로 I/O가 가장 적은 디스크에 배치한다.
- 테이블과 인덱스 테이블 스페이스 중에 I/O가 많은 테이블 스페이스는 별도의
디스크에 배치한다.
로우 마이그레이션과 로우 체이닝
로우 마이그레이션(Row Migration)
: 데이터 블록에서 수정이 발생하면 수정된 데이터를 해당 데이터 블록에서 저장하지
못하고, 다른 블록의 빈 공간을 찾아 데이터를 저장하는 방식
보통 PCTFREE 가 낮게 설정된 경우 발생
로우 체이닝(Row Chaining)
: 로우 길이가 너무 길어서 테이블 블록 하나에 데이터가 모두 저장되지 않고, 두 개
이상의 블록에 걸쳐 하나의 로우가 저정되어 있는 형태
보통 DB_BLOCK_SIZE 가 너무 작게 지정 혹은 LOB 타입 사용시
로우 마이그레이션 확인
sys@ARTDOM>analyze table scott.emp compute statistics ; Table analyzed. sys@ARTDOM>select num_rows, chain_cnt from dba_tables where table_name ='EMP'; NUM_ROWS CHAIN_CNT ---------- ---------- 14 0
로우 체이닝 확인
사전 실행[VLDB:아래 SQL 을 실행 하여 CHAINED\_ROWS 테이블을 사전 생성 해야한다.]
sys@ARTDOM>!ls /app/oracle/product/10.1.0/rdbms/admin/utlchain.sql /app/oracle/product/10.1.0/rdbms/admin/utlchain.sql sys@ARTDOM>analyze table scott.emp list chained rows into CHAINED_ROWS ; Table analyzed. sys@ARTDOM>select count(*) from CHAINED_ROWS where table_name =upper('EMP'); COUNT(*) ---------- 0
4) SQL 문장 튜닝
SQL 문장을 작성할 때 꼭 알고 있어야 할 사항
- 접근 경로에 대한 우선순위를 알고 있어야 한다.
1. ROWID에 의한 단일 로우
2. 클러스터 조인에 의한 단일 로우
3. 유일하거나 PK 를 가진 해시 클러스터키에 의한 단일 로우
4. 유일하거나 PK에 의한 단일 로우
5. 클러스터 조인
6. 해시 클러스터 키
7. 인덱스 클러스터 키
8. 복합 컬럼 인덱스
9. 단일 컬럼 인덱스
10. 인덱스가 구성된 컬럼에서 제한된 범위 검색
11. 인덱스가 구성된 컬럼에서 무제한 범위 검색
12. 정렬-병합 조인
13. 인덱스가 구성된 열에서 MAX 또는 MIN
14. 인덱스가 구성된 열에서 ORDER BY
15. 풀 테이블 스캔 - 옵티마이져 모드가 비용 기반 모드인지 규칙 기반 모드인지 알고 있어야 한다.
- 숫자 형식은 숫자 형식의 타입으로 문자 형식은 문자 형식의 타입으로 비교한다.
- WHERE 절 안에 비교하는 조건에 인덱스를 이용해야 할 경우 인덱스 컬럼을 기술한다.
- 여러 개의 컬럼이 인덱스 하나로 지정된 경우 WHERE 절에 모두 기술한다.
- 여러 개의 컬럼이 인덱스 하나로 지정된 경우 앞쪽에 있는 컬럼을 모두 지정하여
인덱스 범위를 조회할 수 있게 한다. - 인덱스를 이용하고자 하는 컬럼을 변형하지 않는다.
- 인덱스 컬럼에 NULL값을 사용하지 않는다.
- 부정형으로 지정할 경우에는 인덱스를 사용하지 않는다.
가능하면 부정형을 사용하지 않는다. - OR를 사용하면 인덱스를 이용하지 않을 수 있다.
- 불필요하게 DUAL 테이블을 이용하지 않는다.
- WHERE 조건절에 걸린 인덱스가 데이터를 20% 이상 반환하리라 예상되면 인덱스 스캔을
피한다. - 불필요하게 DBMS 에서 제공된 함수(SUM,SGIN,DECODE,NVL 등)를 사용하지 않는다.
- 인덱스가 걸려있는 컬럼에 대해 LIKE 형식으로 비교하는 경우에는 반드시 뒤쪽에
비교자(%)가 위치해야 하며, 앞쪽에 위치할 경우에는 인덱스를 이용하지 않는다. - 힌트를 적절하게 사용한다.
![]() | [dual table 정보] – Online Help DUAL is a table automatically created by Oracle along with the data dictionary. – 메타링크 공지:363988.1 Originally, this table was introduced by Oracle for its internal processing, for example, RMAN |
5) 빈번하게 성능에 영향을 주는 기타 요소
테이블에 일련번호(순번)를 증가시키는 방법
방법1) 두 개의 SQL 문장으로 처리
SELECT MAX(주문번호) + 1 FROM :V_주문일련번호 FROM 주문 ; INSERT INTO 주문(주문일련번호, COL2, COL3...) VALUES ( V_주문일련번호, 'XXX','XXX'...);
방법2) MAX(칼럼) + 1 을 이용한 채번 방법
INSERT INTO 주문(주문일련번호, COL2, COL3... ) SELECT DECODE(MAX(주문일련번호), NULL, 0, MAX(주문일련번호))+1 주문일련번호, :COL2값... FROM 주문 INSERT INTO 주문(주문일련번호, COL2, COL3... ) SELECT DECODE(MAX(주문일련번호), NULL, 0, MAX(주문일련번호))+1 주문일련번호, :COL2값... FROM 주문 WHERE 지점코드 ='XX' AND 주문일자 ='2002-01-01 -- WHERE 절을 통해서 충분하게 값을 걸러주어 MAX 부하를 줄인다.
방법3) 시퀀스 테이블을 이용한 채번 방법
CREATE SEQUECNE 주문_SEQ
INCREMENT BY 1 ;
INSERT INTO 주문( 주문일련번호, COL2, COL3 ... )
VALUES ( 주문_SEQ.NEXTVAL, 'XXX','XXX'...);
방법4) 채번 테이블을 이용한 채번 방법
세 가지 SQL은 트랜잭션 하나로 처리 되어야 정확한 데이터 관리가 가능하다.
1) 신규 일련번호 채번 ( FOR UPDATE ~ ) SELECT 최종일련번호 + 1 INTO :V_주문일련번호 FROM 주문 WHERE 지점코드 ='01' AND 주문구분 ='인터넷'; 2) 본 테이블에 데이터 입력 INSERT INTO 주문(주문일련번호, COL2, COL3... ) VALUES (V_주문일련번호, 'XXX','XXX'...); 3) 채번 테이블 수정 UPDATE 주문채번테이블 SET 최종일련번호 = :V_주문일련번호 WHERE 지점코드 = '01' AND 주문구분 = '인터넷'
방법4) 인덱스 역방향 정렬을 이용한 채번 방법 [VLDB: 가장 좋은 방법]
INSERT INTO 주문(주문일련번호, COL2, COL3... ) SELECT /*+ INDEX_DESC(B i_01) */ <-- 인덱스 i_01 일때 인덱스를 역정렬함 DECODE(MAX(주문일련번호), NULL, 1, 주문일련번호+1), 'XXXX','XXX'... FROM 주문 A, ( SELECT 0 SER FROM DUAL ) B WHERE A.주문일련번호 = B.SER(+) <-- 데이타가 하나도 없을 때 채번하기 위함 AND ROWNUM = 1 ;
갑작스런 대용량 테이블의 성능 저하 원인과 조치 방법
주로 인덱스에서 문제가 발생한 경우다.
- 생성된 인덱스가 깨진 경우
- 인덱스 레벨이 깊어진 경우
- 인덱스 구조에 수정/삭제가 자주 발생한 결과 불필요한 인덱스로 인해
성능이 저하되는 경우
1) 인덱스에 대해 ANALYZE 를 수행
sys@ARTDOM>analyze index scott.BIG_INDEX estimate statistics ; Index analyzed. sys@ARTDOM>alter session set db_file_multiblock_read_count=256; Session altered. sys@ARTDOM>alter session set sort_area_retained_size=100000000; Session altered. sys@ARTDOM>alter session set sort_area_size=100000000; Session altered. sys@ARTDOM>analyze index scott.BIG_INDEX estimate statistics ; Index analyzed.
2)인덱스 레벨을 검사 [VLDB: 적정수준 100만 ROW \- 3 LEVEL]
sys@ARTDOM>select blevel, leaf_blocks from dba_indexes where index_name ='BIG_INDEX'; BLEVEL LEAF_BLOCKS ---------- ----------- 1 230
3) 인덱스를 대체한다. [VLDB: 재생성한다]
sys@ARTDOM>alter index scott.big_index rebuild ; Index altered.
문서에 대하여
- 이 문서는 오라클클럽 [대용량 데이터베이스 스터디] 모임에서 작성하였습니다.
- 이 문서의 내용은 데이터베이스 설계와 구축(개정판) 이춘식 저 서적을 스터디 하면서 정리한 내용 입니다.
- 이 문서를 다른 블로그나 홈페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
문서정보
- 이 문서는 구루비에서 작성하였습니다.
- 이 문서를 다른 블로그나 홈페이지에 게재하실 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 출처 : http://wiki.gurubee.net/pages/viewpage.action?pageId=1966795&
- 구루비 지식창고의 모든 문서는 크리에이티브 커먼즈의 저작자표시-비영리-동일조건변경허락(BY-NC-SA) 라이선스에 따라 자유롭게 사용할 수 있습니다.