- PCTFREE
블록 내에 행을 수정하거나 업데이트 할 때 발생 할 수 있는 행의 크기 증가에 대비하여 예약된 공간. 초기 입력시에는 이 공간을 제외하고 입력된다. PCTFREE가 부족하면 데이터 수정이나 업데이트 시 행이전(ROW MIGRATION)이 발생하게 된다.

- PCTUSED
새로운 행이 블록에 추가되기 전에 행데이터와 오버헤드에 대해 사용될수 있는 블록의 최소 퍼센트이다. 즉, 기존의 데이터가 수정이나 삭제등으로 PCTUSED보다 값이 작아지면 이 블록에 한하여 입력이 가능하다.

- INITRANS
블록에 동시에 엑세스 가능한 트렉젝션의 초기수를 나타낸다. (기본값 : 1)
INITRANS를 낮게 설정하는 경우는 테이블이 크고 테이블에 엑세스하는 사용자의 수가 적을 경우이고, 높게 설정하는 경우는 엑세스하는 사용자가 많을 경우이다.

- MAXTRANS
동시에 엑세스 가능한 트렉젝션의 최대값으로 INITRANS의 상대적 개념이다. (기본값 : 255)
MAXTRNAS가 너무 낮은 경우 이 트렉젝션을 초과한 사용자가 엑세스한 경우 앞의 사용자가 커밋이나 롤백하기 까지 기다려야하는 경우가 발생한다.

- FREELIST
테이블로 데이터를 INSERT 하기 위하여 미리 할당하는 프리 블록의 리스트 수를 지정.

- NOCACHE
NOCACHE 옵션은 'DB의 캐시를 사용하지 않겠다'는 파라미터로서 이것을 CACHE로 지정하면 한번에 20개의 값을 캐시한다. 기본값은 NOCACHE이다.

ex)
USING INDEX
TABLESPACE TSI_BIO01 PCTFREE 20
STORAGE ( INITIAL 16384 NEXT 471556096 PCTINCREASE 80 ))
TABLESPACE TSD_BIO01
PCTFREE 20
PCTUSED 80
INITRANS 1
MAXTRANS 255
STORAGE (
INITIAL 1064960
NEXT 1048576
PCTINCREASE 0
MINEXTENTS 1
MAXEXTENTS 2147483645
FREELISTS 1 FREELIST GROUPS 1 )
NOCACHE;

왜 PCTFREE, PCTUSED 가 필요한가?
ROW CHANNING 현상과 ROW MIGRATION 현상에 대하여 알아야 한다.
ROW CHANNING은 DB_BLOCK_SIZE보다 너무 큰 데이터가 들어왔을 경우 인접한 다른 블록까지 데이터가 넘어가는 것을 말한다.
이런 경우, 만약에 큰 데이터의 특징을 가진다면 LOB TYPE으로 다른 TABLESPACE에 저장하는 것이 옳다.
하 지만 ROW CHANNING은 일반적인 현상이다. 물론 9I 일 경우엔 파라미터에 DB_?K_CACHE_SIZE 를 주고 ?K로 CREATE TABLESPACE ~~ BLOCKSIZE ?K; 로 정하면 더 DB_BLOCK_SIZE 보다 더 큰 BLOCK_SIZE를 가지는 TABLESPACE를 만들고 그 안에 데이터를 넣는다면 ROW CHANNING을 방지할 수 있다.
이 경우 ROW CHANNING은 어쩔 수 없는 현상이다.
하지만, ROW MIGRATION은 꼭 막아야 하는 사항이다.
이것을 예를 들어 보자.

a. A라는 테이블에 10번째 값을 INSERT
b. 이어서 11번째 값을 INSERT
c. 그런데 10번째 값을 유저가 UPDATE시켰는데, UPDATE한 데이터가 예전의 데이터보다 크기가 크다!
d. 이때 DB BLOCK의 11번째 값 때문에 여유공간이 없어서 다른 BLOCK으로 해당 데이터를 이동을 하게 된다.

이런 경우가 자주 일어나는 것은 좋지 않다. 그래서 PCTFREE, PCTUSED이라는 개념이 생긴 것이다.

PCTFREE 10, PCTUSED 40 이라고 한다면?
초기 빈 블록에 데이터가 들어가다가 PCTUSED 40%를 넘겼다. 그래도 계속해서 INSERT를 한다.
그러다가 PCTFREE 10% 즉 데이터가 90%넘게 채워질 경우에는 더 이상 데이터가 들어가지 않고 블록에 여유공간을 남겨둔다.
FILE HEADER에서 FREELIST라는 것을 관리하는데 이것은 이 SEGMENT가 들어갈 빈공간이 있는지를 확인하는 것이다.
이 상의 경우에서 데이터 기록량이 90%를 넘기면 (즉, PCTFREE공간이 10% 이하가 된다면) 그 블록을 FREELIST에서 제거를 하고 그 블록은 INSERT를 중단하고 다른 FREELIST에 등록된 빈 블록에 데이터를 넣을 것이다.
나중에 데이터가 UPDATE가 될 경우를 블록의 10%만큼 미리 준비하는 것이다.

만약, 그 블록의 데이터마저 줄어든다면?
90%보다 줄어들 경우 계속해서 0까지 줄어든다면, 그 블록을 FREELIST에서 삭제된 상황이니 더 이상 INSERT가 되지 않는다.
이 경우를 대비하여 어떤 기준을 마련해두어야 한다.
PCTUSED는 이렇게 BLOCK에 데이터가 없어질 경우의 최소값을 말한다.
즉, 최소한 PCTUSED 만큼은 데이터가 들어가서 DB BLOCK의 낭비를 최소화 하자는 것이다.
이것이 PCTUSED가 필요한 이유이다.

90%이상으로 데이터를 채운 블록에서 데이터가 삭제되어 90% 미만로 떨어지게 되었다.
즉 PCTFREE값이 10% 보다 여유공간이 더 생기는 것이다. 하지만 오라클은 PCTFREE 10%보다 더 큰 여유공간이 생겨도 FREELIST에 그 블록을 추가하지 않는다. 즉, 데이터가 점점 줄다가 60%정도의 데이터가 되더라도 FREELIST에 등록하지 않는다.

PCTUSED 보다 적어지는 상황이 생길 경우는?
PCTUSED 40% 보다 적어지는 상황이 생길 경우가 되어서야 비로소 데이터를 넣을 수 있도록 FREELIST에 등록한다.
하지만 9I에서는 PCTFREE, PCTUSED 방법은 권하지 않는다.
SEGMENT SPACE MANAGEMENT AUTO 절을 넣어서 AUTO로 관리하도록 한다.

※ AUTO방식
AUTO방식의 경우는 PCTFREE만 관리한다.
블록을 25%씩 4개로 나눠 관리하는 방식이다. AUTO를 쓰면 데이터 블록의 낭비를 막고 ROW MIGRATION도 해결해준다. 수동은 권하지 않음!!!

STORAGE ( INITIAL 16384 NEXT 471556096 PCTINCREASE 80 ))
이상에서 STORAGE 절은 EXTENT할당 방식을 말한다.
두가지 방식이 있는데, 8I에서는 DEFAULT가 EXTENT를 할당할 때에 DICTIONARY EXTENT MANAGED TABLESPACE를 사용했다.
물론 이때도 LOCALLY EXTENT MANAGED TABLESPACE를 만들 수는 있다.
9I에서는 LOCALLY EXTENT MANAGED TABLESPACE가 DEFAULT값이다.

이상의 차이는 EXTENT 할당하는 방식에 따른다.
DICTIONARY EXTENT TABLESPACE를 생성할 경우엔 이 테이블스페이스의 EXTENT 할당시에 그 정보를 SYSTEM TABLESPAE의 BASE TABLE에서 가져온다.
하 지만, EXTENT할당을 여기저기서 하다보니 SYSTEM TABLESPACE를 조회해서 EXTENT를 어디를 할당하면 될 것인지 확인하고 EXTENT를 할당 후 할당정보를 SYSTEM TABLESPACE에 저장한다. (병목현상 심함!)

그러나, LOCALLY EXTENT MANAGE TABLESPACE의 경우엔 그렇지 않다.
SYSTEM TABLESPACE의 BASE TABLE에서 EXTENT 여유공간 정보를 가져오는 것이 아니라 해당 데이터파일 헤더에 직접 BITMAP BLOCK으로 저장된다.
그래서 EXTENT할당시에 SYSTEM TABLESPACE에서 찾아서 할당하는 것이 아니라 자신이 속한 테이터파일의 헤더의 BITMAP BLOCK에서 찾겠죠. (경합현상이 거의 발생하지 않는다!)
오라클사에서는 DICTIONARY 방식을 사용하지 말고 LOCALLY TABLESPACE를 사용하도록 권한다.

9I에서 SYSTEM TABLESPACE가 LOCALLY TABLESPACE일 경우, 일반 TABLESPACE생성시 DEFAULT STORAGE절(DICTIONARY 방식)은 사용되지 않는다. (에러발생!)
하지만 SYSTEM TABLESPACE가 DICTIONARY TABLESPACE일 경우엔 DEFAULT STORAGE절(DICTIONARY 방식)을 통해서 CREATE TABLESPACE를 사용할 수 있다.

만약, CREATE TABLE 절에 STORAGE를 준다면 어떻게 될까?
이런 경우 EXTENET MANAGEMENT LOCAL 방식의 경우엔 질문사항인 STORAGE 절을 주게 되면 모두 무시된다. 즉, TABLESPACE에서 정한 UNIFORM SIZE대로(DEFAULT라면 1M 만큼)의 EXTENT를 할당한다.

SYSTEM TABLESPACE가 DICTIONARY TABLESAPCE라면?
이 경우에는 일반 TABLESPACE를 만들 경우에 DEFAULT STORAGE절을 지정할 수 있다. 하지만, CREATE TABLE 명령에서 질문과 같이 STORAGE절을 주게 되면 TABLESPACE의 설정은 모두 무시되고 CREATE TABLE 설정을 따른다.

STORAGE ( INITIAL 16384 NEXT 471556096 PCTINCREASE 80 ))는 무엇을 뜻하는가?
SYSTEM TABLESPACE가 LOCALLY EXTENT MANAGED TABLESPACE에서는 이상의 절을 이용하는 것이 불가능하므로, DICTIONARY EXTENT MANAGED TABLESAPCE라고 할 수 있다. 또한 TABLESPACE도 DICTIONARY EXTENT MANAGED TABLESAPCE이다.

CREATE TABLE TEST ( ID NUMBER ) STORAGE STORAGE ( INITIAL 16384 NEXT 471556096 PCTINCREASE 80 ));
초 기에 이 테이블에 EXTENT는 16384 바이트만큼을 미리 할당한다. 그 후 EXTENT안에 DB BLOCK들에 데이터가 들어갔는데 데이터가 많이 들어가서 모두 데이터가 찼을 경우 새로운 EXTENT를 할당 한다. 이때에 NEXT 만큼을 할당하는 것이다.
PCTINCREASE 80은 그 다음의 경우, 80% 만큼 더 크게 늘어난다는 것이다.

EXTENT1 에서는 16384
EXTENT2 에서는 16384 + 471556096
EXTENT3 에서는 (16384 + 471556096 + 471556096 ) * ( 1 + 0.8 )

이렇게 PCTINCREASE를 쓰게 되면 쓸데없이 한꺼번에 EXTENT를 할당받으므로 다른 TABLE에서 그 만큼 이 공간을 쓰지 못하게 된다. 따라서, PCTINCREASE는 쓰면 안된다!
그리고, DICTIONARY방식은 쓰지 말고 LOCALLY 방식으로 UNIFORM SIZE를 지정하라!
UNIFORM SIZE는 대부분의 경우 10M 정도로 UNIQUE하게 주면 적당하다. (너무 크면 안됨!)

여러 테이블의 데이터가 들어가는데 너무 많은 EXTENT가 생겨서 다른 테이블의 데이터와 섞이지 않나?
SMON이라는 오라클 프로세스가 알아서 하므로, 고려할 바 없다.


★최종 정리★

PCTFREE 20
: UPDATE를 위해서 DB BLOCK에 최소한 20% 정도의 공간을 남겨두겠다.

PCTUSED 80
: PCTFREE로 인한 공간낭비를 막기 위해서 최소한 80% 만큼의 데이터는 꼭 넣겠다.

INITRANS 1
: SEGMENT에 트랜젝션이 최소 한개 이상 걸릴 수 있도록 한다.

MAXTRANS 255
: SEGMENT에 트랜잭션이 최대 255개까지 걸릴 수 있도록 한다.

INITIAL 1064960
: 초기의 EXTENT 크기

NEXT 1048576
: 초기 EXTENT할당후 EXTENT가 부족할 경우 다음 EXTENT 할당 크기

PCTINCREASE 0
: 0%씩 늘이겠다. (무시됨!)

MINEXTENTS 1
: 최소한의 EXTENT를 할당하겠다.(INITIAL 10K 인데 MINEXTENTS가 2 라면? TABLE을 생성하면서 20K를 미리 할당. 20부터 시작.)

MAXEXTENTS 2147483645
: 최대한의 EXTENT. (현재값은 데이터가 커지면 문제있다)

FREELISTS 1 FREELIST GROUPS 1
: 데이터블록의 SEGMENT관리에서 한개 FREELIST에서 FREE BLOCK을 찾고 데이터를 넣는 것에 많은 트랜잭션이 처리를 할 경우 성능이 나빠지게 된다. 그래서 FREELIST의 경우에 여러개가 있으면 분산이 가능하다. FREELIST GROUP은 FREELIST를 몇개를 FREELIST GROUP으로 사용한다는 의미이다.

※EXTENT : 보조 기억 장치에서, 한 파일이 연속적으로 기록되어 있는 일련의 블록

'Database > Oracle' 카테고리의 다른 글

Hash Partition  (0) 2010.04.12
오라클 기본 용어들  (0) 2010.04.08
Sort Merge Join  (0) 2010.04.01
Nested Loop Join - 중첩 루프 조인  (0) 2010.04.01
드라이빙 테이블이란?  (0) 2010.03.30

스칼라 서브쿼리 : SELECT 절에 나오는 서브쿼리
인라인 뷰 : From 절 뒤에 오는 서브 쿼리
서브 쿼리 : Where 절 뒤에 오는 서브 쿼리

'Database > DB Tip' 카테고리의 다른 글

몽고 쿼리 응용  (0) 2013.10.08
DB 전문가로 산다는 것 (1)  (1) 2010.01.22

Sort Merge Join이란 양쪽 테이블의 처리범위를 각자 액세스하여 정렬한 결과를 차례로 스캔하면서 연결고리의 조건으로 머지해 가는 방식을 말한다. 이 방식은 경우에 따라 Nested Loop Join보다 훨씬 빨라지는 경우도 많이 있으며 랜덤 액세스가 줄어들어 시스템의 부하를 감소시키지만 일반적으로 Nested Loop Join 보다는 사용되는 빈도가 적은 편이다.

이 방식의 가장 큰 특징은 상대방에게 아무런 값도 받지 않고 자신이 가지고 있는 조건만으로 처리범위가 정해지며, 랜덤 액세스를 줄일 수는 있으나 항상 전체범위처리를 한다는 것이다.

1. 특징
1) 동시적으로 처리된다. 테이블 각자가 자신의 처리범위를 액세스하여 정렬해 둔다.
2) 각 테이블은 다른 테이블에서 어떠한 상수값도 제공받지 않는다. 즉, 자신에게 주어진 상수값에 의해서만 범위를 줄인다.
3) 결코 부분범위처리를 할 수가 없으며, 항상 전체범위처리를 한다.
4) 주로 스캔방식으로 처리된다. 자신의 처리범위를 줄이기 위해 인덱스를 사용하는 경우만 랜덤 액세스이고 머지작업은 스캔방식이다.
5) 주어진 조건에 있는 모든 컬럼들이 인덱스를 가지고 있더라도 모두가 사용되는 것은 아니다. 연결고리가 되는 컬럼은 인덱스를 전혀 사용하지 않는다.
6) 조인의 방향과는 전혀 무관하다.
7) 스스로 자신의 처리범위를 줄이기 위해 사용되는 인덱스는 대개 가장 유리한 한가지만 사용되어진다. 그러나 그 외의 조건들은 비록 인덱스를 사용하지 못하더라도 작업대상을 줄여 주기 때문에 중요한 의미를 가진다.

2. 사용기준
1) 전체 범위처리를 하는 경우에 주로 유리해진다.
2) 상대방 테이블에서 어떤 상수값을 받지 않고도 처리범위를 줄일 수 있는 상태인 경우 주로 유리해 질 수 있다. 상수값을 받아 처리(Nested Loop Join)한 범위의 크기와 처리범위를 줄여 처리(Sort Merge Join)한 범위의 크기를 대비해보아 상수값을 받아 줄여진 범위가 약 30% 이상이라면 Sort Merge Join이 일반적으로 유리해진다. 그러나 부분범위처리가 되는 경우라면 전혀 달라질 수 있다. 이런 경우는 처리할 전체범위를 비교하지 말고 첫번째 운반단위에 도달하기 위해 액세스하는 범위애 대해서 판단해야 한다.
3) 주로 처리량이 많은 경우 (항상 전체 범위처리를 해야 하는 경우)에 유리해진다. 그것은 처리방식이 주로 스캔방식이므로 많은 양의 랜덤 액세스를 줄일 수가 있기 때문이다.
4) 연결고리 이상 상태에 영향을 받지 않으므로 연결고리를 위한 인덱스를 생성할 필요가 없을 때 유용하게 사용할 수 있다.
5) 스스로 자신의 처리범위를 어떻게 줄일 수 있느냐가 수행 속도에 많은 영향을 미치므로 보다 효율적으로 액세스할 수 있는 인덱스 구성이 중요한다.
6) 전체범위처리를 하므로 운반단위의 크기가 수행 속도에 영향을 미치지 않는다. 가능한 운반단위를 크게 하는 것이 페치(Fetch) 횟수를 줄여준다. 물론 지나치게 큰 운반단위는 시스템에 나쁜 영향을 미친다.
7) 처리할 데이터량이 적은 온라인 애플리케이션에서는 Nested Loop Join이 유리한 경우가 많으므로 함부로 Sort Merge Join을 사용하지 말아야 한다.
8) 옵티마이저 목표(Goal)가  "ALL_ROWS"인 경우는 자주 Sort Merge Join으로 실행계획이 수립되므로 부분범위처리를 하고자 한다면 이 옵티마이져 목표가 어떻게 지정되어 있는지에 주의하여야 한다.

'Database > Oracle' 카테고리의 다른 글

오라클 기본 용어들  (0) 2010.04.08
오라클 옵션  (1) 2010.04.02
Nested Loop Join - 중첩 루프 조인  (0) 2010.04.01
드라이빙 테이블이란?  (0) 2010.03.30
hint 종류  (0) 2010.03.30

Nested Loop Join이란 먼저 어떤 테이블의 처리범위를 하나씩 액세스하면서 그 추출된 값으로 연결할 테이블을 조인하는 방식이다.

1. 특징
1) 순차적으로 처리된다. 선행테이블(Driving table)의 처리범위에 있는 각각의 로우들이 순차적으로 수행될 뿐만 아니라 테이블간의 연결도 순차적이다.
2) 먼저 액세스되는 테이블(Driving Table)의 처리범위에 의해 처리량이 결정된다.
3) 나중에 처리되는 테이블은 앞서 처리된 값을 받아 액세스된다. 즉, 자신에게 주어진 상수값에 의해 스스로 범위를 줄이는 것이 아니라 값을 받아서 처리범위가 정해진다.
4) 주로 랜덤 액세스 방식으로 처리된다. 선행 테이블의 인덱스 액세스는 첫번째 로우만 랜덤 액세스이고 나머지는 스캔이며 연결작업은 모두 랜덤 액세스이다.
5) 주어진 조건에 있는 모든 컬럼들이 인덱스를 가지고 있더라도 모두가 사용되는 것은 아니다. 연결되는 방향에 따라 사용되는 인덱스들이 전혀 달라질 수 있다.
6) 연결고리가 되는 인덱스에 의해 연결작업이 수행되므로 연결고리 상태가 매우 중요하다. 연결고리의 인덱스 유무에 따라 액세스 방향 및 수행속도에 많은 차이가 발생된다.
7) 연결작업 수행 후 마지막으로 check되는 조건은 부분범위처리를 하는 경우에는 조건의 범위가 넓을수록, 아예 없다면 오히려 빨라진다.

2. 사용기준
1) 부분범위처리를 하는 경우에 주로 유리해진다.
2) 조인되는 어느 한쪽이 상대방 테이블에서 추출된 결과를 받아야 처리범위를 줄일 수 있는 상태라면 항상 유리해진다.
3) 주로 처리량이 적은 경우(많더라도 부분범위처리가 가능한 경우)에 유리해진다. 그것은 처리방식이 주로 랜덤 액세스방식이므로 많은 양의 랜덤 액세스가 발생한다면 수행속도가 당연히 나빠지기 때문이다.
4) 가능한 한 연결고리 이상 상태를 만들지 않도록 주의해야 한다.
5) 순차적으로 처리되기 때문에 어떤 테이블이 먼저 액세스되느냐에 따라 수행속도에 많은 영향을 미치므로 최적의 액세스 순서가 되도록 적절한 조치가 요구된다.
6) 부분범위처리를 하는 경우에는 운반단위 크기가 수행속도에 많은 영향을 미칠 수 있다. 운반단위가 적을 수록 빨리 운반단위를 채울 수 있으나, 폐치(Fetch) 횟수에서는 불리해지는 이중성을 가지고 있다.
7) 선행 테이블의 처리 범위가 많거나 연결 테이블의 랜덤 액세스의 양이 아주 많다면 Sort Merge 조인보다 불리해지는 경우가 많다.

'Database > Oracle' 카테고리의 다른 글

오라클 옵션  (1) 2010.04.02
Sort Merge Join  (0) 2010.04.01
드라이빙 테이블이란?  (0) 2010.03.30
hint 종류  (0) 2010.03.30
대량의 데이터 INSERT(HINT)  (0) 2010.02.01

+ Recent posts