CLOB 타입은 4000바이트 이상인 값만 LOB 세그먼트에 저장한다.
테스트를 위해 11.2 버전에서 아래와 같이 테이블을 생성하자. 데이터베이스 캐릭터 셋은 KO16MSWIN949다.
-- 1-1 DROP TABLE t1 PURGE; CREATE TABLE t1 AS SELECT ROWNUM AS c1 , TO_CLOB (LPAD ('X', 1982, 'X')) AS c2 , TO_CLOB (LPAD ('X', 1983, 'X')) AS c3 FROM XMLTABLE ('1 to 10000');
LOB 세그먼트를 조회해보면 c2 칼럼은 64K, c3 칼럼은 80M를 사용하고 있다. 두 칼럼 모두 BASIC FILE로 생성되었다.
-- 1-2 SELECT a.column_name, a.securefile, b.segment_name, b.bytes, b.blocks FROM user_lobs a , user_segments b WHERE a.table_name = 'T1' AND b.segment_name = a.segment_name; COLUMN_NAME SEGMENT_NAME SECUREFILE BYTES BLOCKS ----------- ------------------------- ---------- -------- ------ C2 SYS_LOB0000197636C00002$$ NO 65536 8 C3 SYS_LOB0000197636C00003$$ NO 83886080 10240 2 행이 선택되었습니다.
데이터 블록 덤프 내용에서 c2 칼럼은 실제 값, c3 칼럼은 LOB 로케이터가 저장되어 있는 것을 확인할 수 있다. c2 칼럼은 4000바이트를 사용하고 있다. 실제 값의 크기는 입력한 값의 2배(3964 = 1982*2)고, Inode 관련 16바이트, LOB 관련 20바이트의 부가 정보가 추가로 저장되는 것을 유추할 수 있다. c3 칼럼은 4002바이트(= (1983*2)+16+20)가 필요하므로 LOB 세그먼트에 저장되었다. 1
-- 1-3 ALTER SYSTEM DUMP DATAFILE 4 BLOCK 587; block_row_dump: tab 0, row 0, @0xfae tl: 4050 fb: --H-FL-- lb: 0x0 cc: 3 col 0: [ 2] c1 02 col 1: [4000] 00 54 00 01 02 0c 80 00 00 02 00 00 00 01 00 00 00 c8 be d3 0f 8c 09 00 00 ... LOB Locator: Length: 84(4000) Version: 1 Byte Length: 2 LobID: 00.00.00.01.00.00.00.c8.be.d3 Flags[ 0x02 0x0c 0x80 0x00 ]: Type: CLOB Storage: BasicFile Enable Storage in Row Characterset Format: IMPLICIT Partitioned Table: No Options: VaringWidthReadWrite Inode: Size: 3980 Flag: 0x09 [ Valid DataInRow ] Future: 0x00 (should be '0x00') Blocks: 0 Bytes: 3964 Version: 00000.0000000001 Inline data[3964] Dump of memory from 0x000000001C2C3457 to 0x000000001C2C43D3 01C2C3450 00010000 00580058 00580058 [....X.X.X.X.] 01C2C3460 00580058 00580058 00580058 00580058 [X.X.X.X.X.X.X.X.] Repeat 246 times 01C2C43D0 28580058 [X.X(] col 2: [40] 00 54 00 01 02 0c 80 00 00 02 00 00 00 01 00 00 00 c8 be d4 00 14 05 00 00 00 00 00 0f 7e 00 00 00 00 00 02 01 00 02 2d LOB Locator: Length: 84(40) Version: 1 Byte Length: 2 LobID: 00.00.00.01.00.00.00.c8.be.d4 Flags[ 0x02 0x0c 0x80 0x00 ]: Type: CLOB Storage: BasicFile Enable Storage in Row Characterset Format: IMPLICIT Partitioned Table: No Options: VaringWidthReadWrite Inode: Size: 20 Flag: 0x05 [ Valid InodeInRow(ESIR) ] Future: 0x00 (should be '0x00') Blocks: 0 Bytes: 3966 Version: 00000.0000000002 DBA Array[1]: 0x0100022d end_of_block_dump
12.2 버전에서 동일한 테스트를 진행해보자. CLOB 칼럼의 길이를 각각 1984, 1985로 변경했다.
-- 2-1 DROP TABLE t1 PURGE; CREATE TABLE t1 AS SELECT ROWNUM AS c1 , TO_CLOB (LPAD ('X', 1984, 'X')) AS c2 , TO_CLOB (LPAD ('X', 1985, 'X')) AS c3 FROM XMLTABLE ('1 to 10000');
-- 2-2 SELECT a.column_name, a.segment_name, a.securefile, b.bytes, b.blocks FROM user_lobs a , user_segments b WHERE a.table_name = 'T1' AND b.segment_name = a.segment_name; COLUMN_NAME SEGMENT_NAME SECUREFILE BYTES BLOCKS ----------- ------------------------- ---------- --------- ------ C2 SYS_LOB0000281769C00002$$ YES 131072 16 C3 SYS_LOB0000281769C00003$$ YES 100859904 12312 2 행이 선택되었습니다.
데이터 블록 덤프를 확인해보면 11.2 버전과 유사한 내용을 확인할 수 있다. c2 칼럼이 3999바이트를 사용했으므로 SECURE FILE은 36바이트가 아닌 31바이트의 부가 정보를 저장하는 것으로 보인다.
-- 2-3 ALTER SYSTEM DUMP DATAFILE 7 BLOCK 563; block_row_dump: tab 0, row 0, @0xfb1 tl: 4047 fb: --H-FL-- lb: 0x0 cc: 3 col 0: [ 2] c1 02 col 1: [3999] 00 70 00 01 02 0c 80 80 00 02 00 00 00 01 00 00 01 4d 98 65 0f 8b 48 90 0f ... col 2: [38] 00 70 00 01 02 0c 80 80 00 02 00 00 00 01 00 00 01 4d 98 66 00 12 40 90 00 0c 21 00 0f 82 01 00 01 01 c0 02 1b 01 end_of_block_dump
CLOB 타입의 저장 방식은 [ENABLE | DISABLE] STORAGE IN ROW 옵션을 통해 제어할 수 있다. 아래 쿼리는 c2 칼럼에 DISABLE STORAGE IN ROW 옵션을 사용했다.
-- 3-1 DROP TABLE t1 PURGE; CREATE TABLE t1 LOB (c2) STORE AS (DISABLE STORAGE IN ROW) LOB (c3) STORE AS (ENABLE STORAGE IN ROW) AS SELECT ROWNUM AS c1 , TO_CLOB (LPAD ('X', 1984, 'X')) AS c2 , TO_CLOB (LPAD ('X', 1985, 'X')) AS c3 FROM XMLTABLE ('1 to 10000');
LOB 세그먼트를 조회해보면 c2, c3 칼럼은 모두 96M를 사용하고 있는 것을 확인할 수 있다.
-- 3-2 SELECT a.column_name, a.segment_name, a.securefile, b.bytes, b.blocks FROM user_lobs a , user_segments b WHERE a.table_name = 'T1' AND b.segment_name = a.segment_name; COLUMN_NAME SEGMENT_NAME SECUREFILE BYTES BLOCKS ----------- ------------------------- ---------- --------- ------ C2 SYS_LOB0000282050C00002$$ YES 100859904 12312 C3 SYS_LOB0000282050C00003$$ YES 100859904 12312 2 행이 선택되었습니다.
CLOB 데이터가 행에 저장되면 부가적인 I/O가 발생하지 않으므로 쿼리의 성능이 향상될 수 있지만, 테이블 세그먼트 크기가 커지므로 CLOB 값을 조회하지 않을 경우 쿼리의 성능이 저하될 수도 있다. 조회 유형에 따라 적절한 옵션을 사용해야 할 필요가 있다.
- Byte Length가 2로, 4000바이트 미만의 문자열을 CLOB에 저장하면 공간 낭비가 발생하는 것을 알 수 있다. [본문으로]
'Oracle > Administration' 카테고리의 다른 글
인덱스 명명 규칙 (0) | 2019.08.19 |
---|---|
파티션 통계정보 복사 (0) | 2019.07.26 |
Covered 인덱스와 인덱스 브랜치 블록 (0) | 2019.01.06 |
CHAR vs VARCHAR2 (0) | 2019.01.01 |
Intra-block row chaining (0) | 2018.12.28 |