테이블스페이스 공간 관리
테이블스페이스 공간 관리#
이 절에서는 Altibase의 테이블스페이스 공간을 관리하는 방법에 대하여 설명한다.
언두 테이블스페이스 크기 계산#
언두 테이블스페이스(Undo Tablespace)는 언두 세그먼트를 저장하기 위해 사용된다. 언두 테이블스페이스가 부족할 경우 트랜잭션 성능에 영향을 줄 수 있으므로 DBA는 이를 적절한 크기로 관리해야 한다.
만약 업무 시스템에서 변경 트랜잭션, 특히 오랜 시간동안 구문이 실행되는 트랜잭션이 자주 발생하는 경우에는 언두 세그먼트가 계속 확장될 것이다. 이는 언두 테이블스페이스의 공간 부족을 초래할 수 있다.
사용자는 언두 테이블스페이스를 자동 확장 모드로 설정하거나, 대략적인 최대 크기를 예측하여 그 예측치를 최대 크기로 지정한 고정 크기 모드로 설정할 수 있다.
언두 테이블스페이스의 자동 확장 모드#
사용자가 처음으로 애플리케이션을 수행하는 경우 얼마만큼의 언두 테이블스페이스 공간이 필요한지 알기가 쉽지 않다. 이런 경우에는 언두 테이블스페이스의 자동 확장 모드를 활성화하여 필요한 공간까지 자동으로 확장되도록 한다.
Altibase는 애플리케이션 개발 환경에서 언두 테이블스페이스의 용량을 계획하기 쉽도록 자동 확장 모드를 제공한다. 기본적으로 언두 테이블스페이스는 자동 확장 모드로 설정되며, ALTER TABLESPACE 구문으로 변경할 수 있다.
언두 테이블스페이스의 고정 크기 모드#
사용자가 고정 크기의 언두 테이블스페이스를 사용하고 싶다면, 필요한 용량을 예측해야 한다. 이를 위해서 사용자는 애플리케이션이 수행되는 동안 사용되는 TSS 세그먼트 공간과 언두 세그먼트 공간의 사용 패턴을 수집하여 분석해야 한다.
필요한 언두 테이블스페이스 크기는 일반적으로 다음과 같은 계산식으로 대략적인 산출이 가능하다.
언두 테이블스페이스 크기
= Long-Term 트랜잭션 수행 시간(sec) *
(초당 할당되는 언두 페이지 개수 + 초당 할당되는 TSS 페이지 개수) *
페이지 크기(8KB)
예를 들어 Long-Term 트랜잭션의 수행 시간이 600초(10분)이고 초당 언두 페이지 1000개와 TSS 페이지 24개가 할당된다면, 10 x 60 x (1000 + 24) x 8KB = 4800MB이므로 약 4.7GB 정도가 필요하다.
이와 같이 예측하는 것이 어렵다면, 디스크 공간이 허락하는 한 충분히 넉넉한 크기를 언두 테이블스페이스에 할당하는 것도 방법이다.
언두 테이블스페이스의 확장#
업무 시스템에서 변경 트랜잭션 (특히 Long-Term 트랜잭션, 즉 트랜잭션이 커밋되기까지 긴 시간이 소요되는 트랜잭션)이 자주 발생하는 경우에 언두 테이블스페이스의 공간 부족이 발생할 수 있다. 이러한 경우에 ALTER TABLESPACE 구문을 이용하여 언두 테이블스페이스에 적정한 크기의 데이터 파일을 추가하거나 파일의 크기를 적당히 늘려준다.
메모리 테이블의 크기 추정#
데이터 크기 계산#
메모리 테이블의 데이터 크기는 각 칼럼의 데이터 타입, 칼럼 정렬 (alignment)를 위한 패딩(padding) 등에 기반해서 예측이 가능하다. 수학 공식으로 표현하면 다음과 같다:
데이터 크기 = [ (각 칼럼의 추정 크기의 합 + 각 칼럼을 위한 패딩 크기의 합) * 데이터 레코드 개수]
데이터 타입 별 추정 크기는 다음 표에서 보여준다.
[표 6-3] 메모리 테이블 크기: 데이터 타입 별 추정 크기(P = Precision, V = Value length)
자료형 | 예측 칼럼 크기 |
---|---|
INTEGER | 4 |
SMALLINT | 2 |
BIGINT | 8 |
DATE | 8 |
DOUBLE | 8 |
CHAR | 2+P |
VARCHAR | 22+V |
NCHAR | 2+(P*2) - UTF8 2+(P*3) - UTF16 |
NVARCHAR | 22+(V*2) - UTF8 22+(V*3) - UTF16 |
BIT | 4+(P/8) |
VARBIT | 22+(P/8) |
BYTE | 2+P |
VARBYTE | 22+V |
FLOAT | 3+(P+2)/2 |
NUMERIC | 3+(P+2)/2 |
위 도표에서 P(Precision)는 테이블 생성 시 결정된 칼럼의 크기를 가리킨다. P보다 긴 데이터는 해당 데이터 타입의 칼럼에 입력될 수 없다. V(Value length)는 입력된 데이터의 실제 길이로, V는 P보다 클 수 없다.
CHAR, NCHAR, BIT 타입 같은 고정 길이 칼럼은 P 만큼의 공간을 항상 점유하므로, 칼럼의 길이는 데이터의 실제 길이에 상관없이 고정된다. 그러나 VARCHAR, NVARCHAR, VARBIT, VARBYTE 같은 가변 길이 칼럼은 점유하는 공간이 데이터 길이에 따라서 가변적이다.
디스크 테이블과 달리, 메모리 테이블은 데이터 접근 속도를 높이기 위한 패딩 공간을 포함한다. 이 공간의 크기는 데이터 타입과 칼럼의 위치에 따라서 가변적이다.
인덱스 크기 추정#
메모리 인덱스는 테이블 데이터가 저장되는 테이블스페이스에 저장되지 않는다. 대신에 이는 메모리 공간에 독립적으로 저장된다. 데이터 저장 위치를 가리키는 포인터가 메모리 인덱스 노드의 각 버킷에 저장되기 때문에, 인덱스 크기는 데이터 타입에 상관없이 포인터 크기와 테이블에 현재 저장된 레코드의 개수에 기반하여 추정할 수 있다.
인덱스 크기 = (데이터 레코드의 개수) * p ( p = 포인터 크기 )
위 공식에서 p는 포인터 크기, 즉 한 포인터를 저장하는데 필요한 크기이다. 32-bit 시스템에서는 이 크기가 4바이트이고, 64-bit 시스템에서는 이 크기가 8바이트이다. 이 공식에서, 인덱스의 크기는 모든 리프 노드 (즉, B트리의 최하위의 노드)의 총 크기만큼이다. B트리에는 리프 노드에 더해서 인터널 노드 (즉, 리프 노드의 상위 노드)가 있는데, 이의 총 크기는 리프 노드 크기의 1/128 에 불과하므로 무시해도 된다. 인덱스 관리에 사용되는 추가 정보를 저장하는 크기도 리프 노드 크기의 1/16 정도로 무시할만큼 작다. 그러므로 모든 리프 노드의 총 크기에 기반해서 인덱스의 총 크기를 계산하면 된다.
그러나 이 공식은 리프 노드의 모든 버킷이 그 안에 키 값을 가지고 있는 상황만을 고려한 것이기 때문에, 이 공식을 이용해서 추정된 값은 인덱스의 실제 크기와 다를 수 있다. 즉, 노드 내에 빈 버킷이 많이 있다면 인덱스의 실제 크기는 추정된 크기보다 많이 클 수 있다. 이 경우 인덱스를 재구축해서 인덱스 크기를 줄일 수 있다.
예제 1#
아래처럼 테이블이 생성된 경우 데이터 크기를 추정해 보자.
CREATE TABLE t1
(
c1 INTEGER,
c2 CHAR(1024),
c3 VARCHAR(1024)
) TABLESPACE user_data01;
이 테이블의 칼럼 C1과 칼럼 C2는 고정 길이 칼럼이고 C3는 가변 길이 칼럼이다. 그러므로 한 레코드의 크기는 칼럼 C3에 따라 변할 것이다. 이를 고려하여 한 레코드의 크기를 계산하면, 아래처럼 T1테이블의 데이터 크기는 (한 레코드 크기 * 레코드 개수)와 같다.
[레코드 헤더] = 32 바이트
[C1 칼럼] = 4 바이트
[C2 칼럼] = 2+P 바이트 = 2+1024 바이트
[C3 칼럼] = 22+V 바이트
칼럼 C3의 데이터 길이가 200바이트이면:
[총 길이] = 32 + ( 4 ) + (2+1024) + (22+200) + padding
= (1284 + padding) 바이트
칼럼 C3의 데이터 길이가 500바이트이면:
[총 길이] = 32 + ( 4 ) + (2+1024) + (22+500) + padding
= (1584 + padding) 바이트
예제 2#
아래 구문으로 생성된 테이블 T1의 인덱스 크기를 계산해 보자. 테이블 T1에는 현재 500,000 레코드가 있고, 시스템은 64-bit이다.
CREATE TABLE t1 ( c1 INTEGER, c2 CHAR(300), c3 VARCHAR(500)) TABLESPACE user_data01;
CREATE INDEX t1_idx1 ON t1( c1, c2, c3 );
T1의 인덱스 크기
[인덱스 크기] = 500,000 records * 8 = 3.814 Megabytes
예제 3#
아래 구문으로 생성된 테이블의 데이터와 인덱스 크기를 계산해 보자. 테이블에는 현재 1,000,000 레코드가 있고, 시스템은 64-bit이다.
CREATE TABLE test001
(
c1 CHAR(8) PRIMARY KEY,
c2 CHAR(128),
n1 INTEGER,
in_date DATE
) TABLESPACE user_data01;
한 레코드의 크기와 총 데이터 크기
[총 길이] = 32[헤더] + (2+8) + (2+128) + (4) + (8) = 184 바이트
[전체 데이터 크기] = [184] * 1,000,000 records = 175.47 MB
인덱스 크기
[전체 인덱스 크기] = 8 * 1,000,000 records = 7.629 MB
이 값은 데이터 크기와 리프 노드의 크기에 기반해서 계산되었기 때문에, 실제로는 페이지 헤더, 인덱스 노드, 그리고 프리 (free) 페이지 관리를 위한 메모리에 사용되는 공간이 추가로 있을 것이다.
디스크 테이블의 크기 추정#
Altibase의 디스크 테이블 크기는 자료형과 데이터의 구성을 바탕으로 계산할 수 있으며 [테이블 로우의 총 길이 * 데이터 건 수] 의 값을 가진다. 다음 표는 자료형 별 길이를 보여준다.
[표 6-4] 디스크 테이블 크기: 데이터 타입 별 추정 크기(P = Precision, V = Value length)
자료형 | 추정되는 칼럼 크기 | ||
---|---|---|---|
Null | 250바이트 이하 | 251바이트 이상 | |
INTEGER | 1 | 5 | X |
SMALLINT | 1 | 3 | X |
BIGINT | 1 | 9 | X |
DATE | 1 | 9 | X |
DOUBLE | 1 | 9 | X |
CHAR | 1 | 1+P | 3+P |
VARCHAR | 1 | 1+V | 3+V |
NCHAR | 1 | 1+P | 3+P |
NVARCHAR | 1 | 1+V | 3+V |
BIT | 1 | 5+(P/8) | 7+(P/8) |
VARBIT | 1 | 5+(V/8) | 7+(V/8) |
BYTE | 1 | 1+P | 3+P |
VARBYTE | 1 | 1+V | 3+V |
FLOAT | 1 | 4+(V+2)/2 | 6+(V+2)/2 |
NUMERIC | 1 | 4+(V+2)/2 | 6+(V+2)/2 |
위 도표에서 P(Precision)는 테이블 생성 시 결정된 칼럼의 최대 크기이다. P 보다 큰 길이를 갖는 데이터는 그 타입의 칼럼에 입력되지 않는다. 또한 고정길이 칼럼인 CHAR, NCHAR, BIT 등은 항상 P 만큼의 공간을 점유하기 때문에, 데이터의 길이와 상관없이 칼럼의 길이는 일정하다.
V(Value length)는 실제로 삽입된 데이터의 실제 길이로, P보다 클 수 없다. 또한 가변 길이 칼럼인 VARCHAR, NVARCHAR, VARBIT, VARBYTE 등은 데이터의 크기에 따라 점유하는 공간의 크기가 달라진다. 따라서 데이터의 크기에 따라 칼럼의 크기가 변한다.
로우(row) 크기 추정#
이 절에서는 테이블 스키마가 다음과 같을 경우, 로우 크기를 계산하는 방법에 대해 설명한다.
CREATE TABLE t1
(
c1 CHAR(32),
c2 CHAR(1024),
c3 VARCHAR(512)
) TABLESPACE user_data02;
이 스키마에서 C1 칼럼과 C2 칼럼은 고정길이 칼럼이며, C3 칼럼은 가변길이 칼럼이다. 따라서 C3 칼럼의 크기에 따라 로우의 크기가 변한다. 또한 칼럼에 널(NULL)이 존재하는지 여부에 따라 로우의 크기가 변한다. 이를 고려하여 로우의 크기를 계산하면 아래와 같으며, 테이블 T1의 크기는 (한 로우의 총 길이 * 데이터 건 수)가 된다.
[로우 헤더] 34 바이트
[C1 칼럼] 1+P 바이트 = 1+32 바이트
[C2 칼럼] 3+P 바이트 = 3+1024 바이트
[C3 칼럼] 3+V 바이트
C3 칼럼의 데이터 크기가 200 바이트인 경우
[총 길이] = 34 + (1+32) + (3+1024) + (1+200) = 1295 바이트
C3 칼럼의 데이터 크기가 500 바이트인 경우
[총 길이] = 34 + (1+32) + (3+1024) + (3+500) = 1597 바이트
C2 칼럼이 널이고, C3 칼럼의 데이터 크기가 300 바이트인 경우
[총 길이] = 34 + (1+32) + (1) + (3+300) = 371 바이트
C3 칼럼이 널인 경우
[총 길이] = 34 + (1+32) + (3+1024) + (0) = 1094 바이트
마지막 칼럼이 널(null)이고 데이터가 없는 경우, 마지막 칼럼은 저장하지 않으므로 크기에 반영되지 않는다.
인덱스(index) 크기 추정#
인덱스의 크기 역시 자료형과 데이터의 구성을 바탕으로 계산할 수 있다. 다음 표는 인덱스 크기 계산 시 사용할 자료형 별 길이를 보여준다.
[표 6-5] 디스크 인덱스 크기: 데이터 타입 별 추정 크기(P = Precision, V = Value length)
자료형 | 인덱스 키의 크기 | ||
---|---|---|---|
Null | 250바이트 이하 | 251바이트 이상 | |
INTEGER | 4 | 4 | X |
SMALLINT | 2 | 2 | X |
BIGINT | 8 | 8 | X |
DATE | 8 | 8 | X |
DOUBLE | 8 | 8 | X |
CHAR | 1 | 1+P | 3+P |
VARCHAR | 1 | 1+V | 3+V |
NCHAR | 1 | 1+P | 3+P |
NVARCHAR | 1 | 1+V | 3+V |
BIT | 1 | 5+(P/8) | 7+(P/8) |
VARBIT | 1 | 5+(V/8) | 7+(V/8) |
BYTE | 1 | 1+P | 3+P |
VARBYTE | 1 | 1+V | 3+V |
FLOAT | 1 | 4+(V+2)/2 | 6+(V+2)/2 |
NUMERIC | 1 | 4+(V+2)/2 | 6+(V+2)/2 |
위 도표에서 P(Precision)와 V(Value length)는 각각 테이블 생성 시 결정된 칼럼의 최대 크기와 실제로 삽입된 데이터의 크기를 의미한다.
한 인덱스의 크기는 다음과 같다.
[ 10(헤더 길이) + (키 칼럼 길이의 합) ] * 데이터 건 수
위의 계산 공식은 leaf node (B*Tree에서 최하위의 노드)의 대략적인 크기이다. 이 외에 internal node(leaf node의 상위 노드)의 크기의 경우, 키 칼럼(key column)의 크기가 작을 경우에는 무시할 수 있을 정도로 그 크기가 작다.
하지만 키 칼럼의 크기가 2KB이상일 경우에는 B*Tree의 깊이가 깊어지고, internal node의 크기가 전체 Leaf Node 크기의 50% 정도까지 될 수 있으므로 이런 경우에는 internal node의 크기를 계산에 포함해야 한다.
다음은 테이블 및 인덱스의 스키마가 다음과 같을 경우, 인덱스의 크기를 계산하는 방법을 보여준다.
CREATE TABLE t1
(
c1 INTEGER,
c2 VARCHAR(500)
) TABLESPACE user_data02;
CREATE INDEX t1_idx1 ON t1( c1, c2 );
C1 칼럼은 Integer 형이므로 항상 4 byte로 크기가 결정된다. C2는 가변길이 칼럼으로 데이터의 크기에 따라 길이가 가변적으로 변한다.
[키 헤더] 10 byte
[C1 칼럼] 4 byte
[C2 칼럼] 1+V byte
C2 칼럼의 데이터 크기가 50 바이트인 경우
[총 길이] 10 + 4 + (1+50) = 65 바이트
C2 칼럼의 데이터 크기가 500 바이트인 경우
[총 길이] 10 + 4 + (3+500) = 517 바이트
C2 칼럼이 널인 경우
[총 길이] 10 + 4 + 1 = 15 바이트
테이블 크기 계산 예제#
테이블 스키마가 다음과 같고 데이터 건 수가 100만 건일 경우에, 로우의 크기와 인덱스의 크기를 포함한 테이블의 크기를 다음과 같이 계산한다.
CREATE TABLE test001
(
c1 CHAR(8) PRIMARY KEY,
c2 CHAR(128),
n1 INTEGER,
in_date DATE
) TABLESPACE user_data02;
로그 크기 및 전체 데이터 크기
로우 크기 : 34[헤더] + (1+8) + (1+130) + (1+4) + (1+8) = 188 바이트
전체 데이터 크기 : [ 188 ] * 100만 건 = 179.29 M 바이트
인덱스 크기
한 로우의 인덱스 크기 : 10[헤더] + (1+8)[C1] = 19 바이트
전체 인덱스 크기 : 19 * 100만건 = 18.12 M 바이트
TEST001 테이블 전체가 차지하는 디스크 크기
179.29 (데이터 크기) + 18.12(인덱스 크기) = 197.41 M 바이트
이것은 데이터의 크기만 계산한 것으로, 실제로는 페이지 헤더, internal node, 세그먼트 관리 영역 등을 추가로 사용하며 그만큼 공간을 더 사용한다. 이러한 부분을 고려하면, 총 테이블스페이스는 약 240M 바이트를 사용하게 될 것이다.
테이블 저장 공간 계산#
위에서 테이블의 크기 계산에 사용된 테이블 TEST001을 기준으로 테이블의 레코드와 인덱스를 모두 저장할 수 있는 테이블의 적정 사이즈를 계산한다. 적정한 테이블 크기를 계산하기 위해서 다음과 같은 사항을 고려해야 한다.
트랜잭션의 유형의 상대 빈도를 고려한다#
특정 테이블에 대하여 갱신 (Update) 트랜잭션이 많이 발생할 경우에는 트랜잭션의 성능을 높이기 위해 PCTFREE를 크게 하고, PCTUSED를 작게 하여 변경 작업을 위해 필요한 빈 공간(free space)을 많이 확보하는 것이 좋다.
변경 트랜잭션이 적고 입력(Insert) 트랜잭션이 주로 발생하는 테이블의 경우에는 반대로 PCTFREE를 작게하고, PCTUSED를 크게 하여 불필요한 빈 공간(free space)을 최소화해야 한다.
PCTFREE#
기본값은 10으로, 디스크 테이블 생성 시 0에서 99 사이의 값을 명시할 수 있다. 이는 테이블의 각 페이지에서 기존 레코드에 대한 변경 연산 등을 위하여 미리 예약한 여유 공간의 비율이다. 따라서 PCTFREE가 10이고 입력(Insert) 트랜잭션만 발생한다고 가정할 경우에 테이블의 전체 크기가 100M 라면 테이블의 레코드와 인덱스를 위해 사용될 수 있는 공간은 90M가 된다.
PCTUSED#
기본값은 40이며 디스크 테이블 생성 시 0에서 99 사이의 값을 명시할 수 있다. 특정 페이지가 PCTFREE에서 명시한 비율에 도달한 후에 변경과 삭제로 인해서 빈 공간의 비율이 40% 미만(39%)으로 될 때까지 해당 페이지에는 삽입 연산이 일어나지 않는다. 따라서 변경이 많이 발생하는 테이블일 경우에는 테이블의 크기를 산정할 때 여유 공간을 많이 확보해야 한다.
[표 6‑6] 트랜잭션 유형의 상대 빈도에 따른 테이블 크기 계산
상황 | 테이블 사이즈 계산 |
---|---|
대부분이 Read Only 트랜잭션이거나 UPDATE 시에 레코드의 크기가 증가 되지 않을 경우 | PCTFREE를 5로 지정하고, PCTUSED를 90으로 지정한 경우 (1) 최소 테이블 크기 계산: TEST001(전체사이즈=215.53M)테이블을 저장하기 위해서 필요한 최소 사이즈는 다음과 같은 공식으로 계산한다. 테이블 전체 사이즈 / [1-(PCTFREE / 100)] = 215.53/0.95 ≒ 227M (2) 가중치 계산: 최소 사이즈에 적절한 크기의 가중치를 추가한다. 가중치는 시스템 상황에 따라 달라질 수 있다. 다음은 가중치 계산의 한가지 예이다. 최소사이즈 * [ 1- (PCTUSED / 100) ] * 2 = 227 * 0.1 * 2 ≒ 45M (3) 따라서 테이블을 총 272M 정도의 사이즈로 생성한다. |
UPDATE가 빈번하고, UPDATE 시에 레코드의 크기가 증가될 경우 | PCTFREE를 20으로 지정하고, PCTUSED를 40으로 지정한 경우 (1) 최소 테이블 크기 계산: TEST001(전체사이즈=213.63M)테이블을 저장하기 위해서 필요한 최소사이즈는 다음과 같은 공식으로 계산한다. 테이블전체사이즈 / [1-(PCTFREE / 100) = 213.63/0.8 ≒ 267M (2) 가중치 계산: 최소 사이즈에 적절한 가중치를 추가한다. 다음은 가중치 계산의 한가지 예이다. 최소 사이즈 * [ 1- (PCTUSED / 100) ] * 2 = 267 * 0.6 * 2 ≒ 320M (3) 따라서 테이블을 총 587M 정도의 사이즈로 생성한다. |
INSERT와 UPDATE 가 자주 발생하지만 UPDATE를 할 때 레코드의 크기가 증가되지 않을 경우 | PCTFREE를 10으로 지정하고, PCTUSED를 60으로 지정한다. |
Note
위의 표에서 설명한 테이블의 사이즈 계산은 절대적인 기준이 아니다. 시스템이 비정상 동작하여 데이터가 갑자기 증가하는 등의 장애 상황에 대한 고려가 필요하다.
적정한 백업 사이즈를 고려한다.#
실제 업무에서 하나의 테이블스페이스에 하나의 테이블만 저장되는 경우는 드물다. 업무단위 또는 백업단위로 테이블을 묶어서 하나의 테이블스페이스에 생성하는 것이 더 효율적이다.
이 경우 테이블스페이스에 대한 백업 소요 시간 등을 고려하여 한 개 테이블스페이스의 적정사이즈를 설정해야 한다.
다음 그림은 데이터베이스 내에서 테이블스페이스를 업무단위 및 백업사이즈를 고려하여 적정사이즈로 분리하여 생성한 것을 보여준다.

테이블스페이스 정보#
Altibase는 테이블스페이스를 관리하기 위해서 테이블스페이스의 상태를 점검하거나 모니터링 하기 위한 성능 뷰와 메타 테이블을 제공한다.
SYSTEM_.SYS_TBS_USERS_
또한 다음의 성능 뷰를 통해 사용자들이 사용하는 데이터베이스의 크기, 사용량, 상태 등의 정보를 확인할 수 있다.
V$TABLESPACES, V$DATAFILES, V$MEM_TABLESPACES