본문 바로가기

데이터 사이언스 DataScience/Data Base 데이터베이스

[Oracle] LOB보다 TABLE 용량이 더 큰 이유

* 문제상황 :

- DMBS버전 : 19c

- CLOB 컬럼을 2개 포함한 테이블에서, 테이블의 용량이 LOB 용량의 10배 가까이 된다.

   (LOB 제외 컬럼 길이는 길지 않음)

 

* 원인분석 : 

일반적으로 LOB은 이름 그대로 Large OBject 를 저장하기 위한 데이터 타입이다. 

게시판의 본문이 컬럼에 통채로 들어가기도 하고, json이나 인터페이스 전문을 통채로 넣기도 한다.

 

그래서 LOB 컬럼 용량이 테이블 용량보다 큰 경우가 많고,

LOB 테이블스페이스와 테이블 테이블스페이스를 분리하기도 한다.

 

그런데, CLOB 컬럼 2개보다 테이블 용량이 10배가 되는 테이블을 발견했다.

 

그 이유는 오라클 DOCS에서 찾을 수 있었다. 

STORAGE IN ROW 옵션이 ENABLE이고 4,000 Bytes 미만인 LOB이 많아서, 

LOB 데이터가 LOB SEGMENT가 아닌 TABLE SEGMENT에 저장되고 있었다.

 

 

* STORAGE IN ROW 옵션

LOB 크기가 VARCHAR2 (4,000) 이하인 경우 LOB은 INLINE으로 저장이 가능하다.

즉, LOB SEGMENT가 아닌 TABLE SEGMENT에 저장 가능하다.

 

<Oracle docs 출처 - Oracle Database SecureFiles and Large Objects Developer's Guide >

The maximum amount of LOB data stored in the row is the maximum VARCHAR2 size (4000). This includes the control information and the LOB value. If you indicate that the LOB should be stored in the row, once the LOB value and control information is larger than approximately 4000, then the LOB value is automatically moved out of the row.

Storage in row 옵션은 ENABLE, DISABLE 2개의 선택이 가능하다.

 

- ENABLE (default) :

  1) LOB size가 4,000 Bytes 미만인 경우, 추가적인 Disk I/O를 줄이기 위해 inline으로 table segment에 저장한다.

  2) LOB size가 4,000 Bytes 초과시, LOB control 정보만 inline에 저장하고, LOB 데이터는 lob segment에 저장한다.

     이 경우에도, 데이터 READ시 DISABLE 옵션보다 빠르게 LOB 정보를 읽을 수 있다.

 

- DISABLE : 

  LOB size가 4,000 Bytes 이하인 경우를 포함, 모든 경우에 table segment에 저장하지 않고 lob segment에 저장한다.

이는 table row size가 커지는 것을 방지하기 때문에

  1) LOB컬럼을 제외한 컬럼의 CRUD가 많다면

  2) TABLE FULL SCAN이 많다면

  3) RANGE SCAN이 많다면 

더 효과적이다.

 

즉, LOB 컬럼 자체 READ가 많은 경우 ENABLE을, 적은 경우 DISABLE을 하는게 효과적이다.

 

Oracle에서는 LOB 테이블의 경우 LOB이 중요한 역할을 하는 경우가 많다고 생각해

STORAGE IN ROW 옵션을 DEFAULT를 ENABLE로 했을 것 같다.

 

 

테스트를 더 해봐야겠지만,

로그성 lob 테이블의 경우 storage in row 옵션을 disable로 할 때, 용량관리가 효율적일 것으로 예상된다.

그 이유는

1) lob이 아닌 컬럼의 압축(compress for oltp)에 더 효율적일 것 같다.

   옵션이 ENABLE인 경우에는, lob 데이터가 inline으로 저장되는 row가 발생하고 

   1개 row가 가지는 block의 크기가 커져 row chaining이 발생해 압축의 효율이 떨어질 것으로 예상된다.

2) lob segment 크기가 커지기 때문에 secure file로 compress 옵션 적용시 더 효과적이다. 

 

 

* LOB 데이터의 길이 분포를 확인할 수 있는 SQL : 

SELECT LEN, COUNT(*)
FROM (
SELECT /*+ FULL(A) PARALLEL(A 4) */
       ROUND(DBMS_LOB.GETLENGTH(COLUMN_NAME) / 100, 0) * 100 AS LEN
FROM TABLE_NAME A
)
GROUP BY LEN
ORDER BY LEN
;

STORAGE IN ROW 옵션이 ENABLE일때,

얼마나 많은 데이터가 INLINE으로 저장될지 대략적으로 유추해볼 수 있어보인다.

 

 

* 참고자료 : 

https://docs.oracle.com/database/121/ADLOB/adlob_tables.htm#ADLOB45300

 

LOB Storage with Applications

As shown in the previous example, specifying a name for the LOB data segment makes for a much more intuitive working environment. When querying the LOB data dictionary views USER_LOBS, ALL_LOBS, DBA_LOBS (see Oracle Database Reference), you see the LOB dat

docs.oracle.com

 

 

 

반응형