#LOB 타입

LOB 타입설명
{code:noneborderStyle=solid}CLOB{code}{code:noneborderStyle=none}문자 LOB, 대량 문자 정보 저장, 기본 캐릭터셋{code}
{code:noneborderStyle=solid}NCLOB{code}{code:noneborderStyle=none}CLOB 과 같으나, 내셔널 캐릭터셋{code}
{code:noneborderStyle=solid}BLOB{code}{code:noneborderStyle=none}이진 LOB, 대량 이진 정보 저장(이미지등){code}
{code:noneborderStyle=solid}BFILE{code}{code:noneborderStyle=none}이진 파일 LOB, 파일에 대한 포인터, 읽기 모드{code}
○ 내부 LOB
Demo#1 (LOB)
{code:sqlborderStyle=solid}
SQL> CREATE TABLE T
2 ( ID INT PRIMARY KEY,
3 TXT CLOB
4 ) SEGMENT CREATION IMMEDIATE;

Table created.

SQL> SELECT DBMS_METADATA.GET_DDL('TABLE', 'T') FROM DUAL;

DBMS_METADATA.GET_DDL('TABLE', 'T')




























---
CREATE TABLE "SCOTT"."T"
( "ID" NUMBER(*,0),
"TXT" CLOB,
PRIMARY KEY ("ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS" ENABLE
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS"
LOB ("TXT") STORE AS BASICFILE (
TABLESPACE "USERS" ENABLE STORAGE IN ROW CHUNK 8192 RETENTION
NOCACHE LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) ;

-- 주요속성: TABLESPACE, STORAGE IN ROW, CHUNK 8192, RETENTION, NOCACHE, STORAGE 절

-- 멀티세그먼트 객체 형식
23:58:08 SCOTT@ORCL> @seg T

OWNER SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE TABLESPACE_NAME SIZE_MB



--


---






---


---
---
KSAPP T TABLE USERS 0
SCOTT SYS_C00168054 INDEX USERS 0
SCOTT SYS_IL000019431 LOBINDEX USERS 0
0C00002$$
SCOTT SYS_LOB00001943 LOBSEGMENT USERS 0
10C00002$$

– LOBINDEX : LOB 데이터 찾기용 (마스터)
– LOBSEGMENT : LOB 데이터 저장용 (디테일)

– LOB컬럼 → LOBINDEX → LOBSEGMENT

|
 
 * LOB 테이블스페이스
  ** 테이블/LOB의 테이블스페이스는 다를 수 있음 : 관리/성능상 분리
  ** LOB은 버퍼 캐시에 못올라가며 DIRECT READ/WRITE 함 (기본 설정)

||Demo#2 (IN ROW 절)||
|{code:sql|borderStyle=solid}
-- ENABLE STORAGE IN ROW : 4000 바이트 이내 LOB 데이터는 테이블 내 컬럼에 저장, 4000 바이트 초과 LOB 데이터는 LOBSEGMENT에 저장
-- DISABLE STORAGE IN ROW : LOB 데이터는 LOBSEGMENT에 저장

00:13:20 SCOTT@ORCL> CREATE TABLE T
00:13:21   2  ( ID      INT PRIMARY KEY,
00:13:21   3    IN_ROW  CLOB,
00:13:21   4    OUT_ROW CLOB
00:13:21   5  )
00:13:21   6  LOB (IN_ROW) STORE AS ( ENABLE STORAGE IN ROW)
00:13:21   7  LOB (OUT_ROW) STORE AS (DISABLE STORAGE IN ROW);

Table created.

Elapsed: 00:00:00.12
00:13:22 SCOTT@ORCL> INSERT INTO T
00:14:11   2  SELECT ROWNUM
00:14:11   3       , OWNER || ' ' || OBJECT_NAME || ' ' || OBJECT_TYPE || ' ' || STATUS
00:14:11   4       , OWNER || ' ' || OBJECT_NAME || ' ' || OBJECT_TYPE || ' ' || STATUS
00:14:11   5    FROM ALL_OBJECTS;

101434 rows created.

Elapsed: 00:00:52.44
00:15:04 SCOTT@ORCL> COMMIT;

Commit complete.

Elapsed: 00:00:00.00

00:23:16 SCOTT@ORCL> DECLARE
00:23:20   2    L_CNT   NUMBER;
00:23:20   3    L_DATA  VARCHAR2(32765);
00:23:20   4  BEGIN
00:23:20   5
00:23:20   6    SELECT COUNT(*)
00:23:20   7      INTO L_CNT
00:23:20   8      FROM T;
00:23:20   9
00:23:20  10    DBMS_MONITOR.SESSION_TRACE_ENABLE;
00:23:20  11    FOR I IN 1 .. L_CNT
00:23:20  12    LOOP
00:23:20  13      SELECT IN_ROW INTO L_DATA FROM T WHERE ID = I;
00:23:20  14      SELECT OUT_ROW INTO L_DATA FROM T WHERE ID = I;
00:23:20  15    END LOOP;
00:23:20  16  END;
00:23:21  17  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:24.62


-- TRACE/TKPROF
SELECT IN_ROW
FROM
 T WHERE ID = :B1

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute 101434      0.07       1.37          0          0          0           0
Fetch   101434      0.04       1.48          0     304302          0      101434
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total   202869      0.11       2.86          0     304302          0      101434


SELECT OUT_ROW
FROM
 T WHERE ID = :B1

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute 101434      0.07       1.22          0          0          0           0
Fetch   101434     13.32       7.70     101434     710038          0      101434
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total   202869     13.39       8.92     101434     710038          0      101434
-- IN_ROW 에 비해서 OUT_ROW 는 LOBSEGMENT 접근(disk:101434) 및 LOBINDEX 접근(query:710038-304302) 자원을 더 필요로 함


00:30:48 SCOTT@ORCL> CREATE SEQUENCE S START WITH 200000;

Sequence created.

Elapsed: 00:00:00.02

00:31:32 SCOTT@ORCL> DECLARE
00:31:35   2    L_CNT NUMBER;
00:31:35   3    L_DATA VARCHAR2(32765);
00:31:35   4  BEGIN
00:31:35   5    DBMS_MONITOR.SESSION_TRACE_ENABLE;
00:31:35   6    FOR I IN 1 .. 100
00:31:35   7    LOOP
00:31:35   8      UPDATE T SET IN_ROW = TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') WHERE ID = I;
00:31:35   9      UPDATE T SET OUT_ROW = TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') WHERE ID = I;
00:31:35  10      INSERT INTO T (ID, IN_ROW) VALUES (S.NEXTVAL, 'Hello World');
00:31:35  11      INSERT INTO T (ID, OUT_ROW) VALUES (S.NEXTVAL, 'Hello World');
00:31:35  12    END LOOP;
00:31:35  13  END;
00:31:36  14  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.21

-- TRACE/TKPROF
UPDATE T SET IN_ROW = TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS')
WHERE
 ID = :B1

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute    100      0.02       0.01          0        200        206         100
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total      101      0.02       0.01          0        200        206         100


UPDATE T SET OUT_ROW = TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS')
WHERE
 ID = :B1

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute    100      0.05       0.07          0       1509       2252         100
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total      101      0.05       0.07          0       1509       2252         100


INSERT INTO T (ID, IN_ROW)
VALUES
 (S.NEXTVAL, 'Hello World')

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute    100      0.00       0.01          0          2        322         100
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total      101      0.00       0.01          0          2        322         100


INSERT INTO T (ID, OUT_ROW)
VALUES
 (S.NEXTVAL, 'Hello World')

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute    100      0.02       0.04          0       1007       1551         100
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total      101      0.02       0.04          0       1007       1551         100
-- IN_ROW 에 비해서 OUT_ROW 는 읽기/쓰기 모두 자원을 더 필요로 함, ENABLE STORAGE IN ROW 추천

|

  • CHUNK 절
    • 인접한 블록의 집합
    • LOB 에서 가장 작은 할당 단위 (오라클 블록 크기의 정수 배로 구성)
    • 주의사항 : 적절한 크기의 CHUNK 설정 (너무 크면 공간 낭비, 너무 작으면 성능 저하)
Demo#3 (RETENTION 절)
{code:sqlborderStyle=solid}
– UNDO 안쓰고 읽기 일관성 제공 (LOBINDEX 는 UNDO 사용)
-- 변경 정보를 LOBSEGMENT 자체 보관 : LOB 데이터가 수정되면 새로운 CHUNK 를 할당하고, 이전 CHUNK 를 남겨둠)

00:57:11 SCOTT@ORCL> CREATE TABLE T
00:57:16 2 ( ID INT PRIMARY KEY,
00:57:16 3 TXT CLOB
00:57:16 4 ) LOB (TXT) STORE AS ( DISABLE STORAGE IN ROW );

Table created.

00:57:18 SCOTT@ORCL> INSERT INTO T VALUES (1, 'Hello World');

1 row created.

00:57:21 SCOTT@ORCL> COMMIT;

Commit complete.

00:57:24 SCOTT@ORCL> DECLARE
00:57:28 2 L_CLOB CLOB;
00:57:28 3
00:57:28 4 CURSOR C IS SELECT ID FROM T;
00:57:28 5 L_ID NUMBER;
00:57:28 6 BEGIN
00:57:28 7 SELECT TXT INTO L_CLOB FROM T;
00:57:28 8 OPEN C;
00:57:28 9
00:57:28 10 UPDATE T SET ID = 2, TXT = 'GoodBye';
00:57:28 11 COMMIT;
00:57:28 12
00:57:28 13 DBMS_OUTPUT.PUT_LINE( DBMS_LOB.SUBSTR(L_CLOB, 100, 1));
00:57:28 14 FETCH C INTO L_ID;
00:57:28 15 DBMS_OUTPUT.PUT_LINE( 'ID = ' || L_ID );
00:57:28 16 CLOSE C;
00:57:28 17 END;
00:57:28 18 /
Hello World
ID = 1

PL/SQL procedure successfully completed.

00:57:29 SCOTT@ORCL> SELECT * FROM T;

ID TXT
---




2 GoodBye

-- 커서 C의 읽기 일관성 : UNDO SEGMENT
– LOB의 읽기 일관성 : LOBSEGMENT
– RETENTION : UNDO_RETENTION 설정에 맞추어 변경된 LOB 데이터를 LOBSEGMENT에 보유 하도록 함 (LOB SEGMENT 가 자꾸 증가 한 원인이 혹시...)
– PCTVERSION : 읽기 일관성을 위해 사용할 LOBSEGMENT 공간 크기를 지정 (기본값 : LOBSEGMENT 크기의 10%)

|

 * CACHE 절
  ** NOCACHE(기본값), CACHE(읽기쓰기캐시), CACHE READS(읽기캐시)
  ** ALTER TABLE tabname MODIFY LOB (lobname) (CACHE | NOCACHE);

 * LOB STORAGE 절
  ** LOBSEGMENT 와 LOBINDEX 에 동일 하게 적용

||Demo#4 (SECUREFILE)||
|{code:sql|borderStyle=solid}
23:11:39 SCOTT@ORCL> CREATE TABLE T1BF
23:12:16   2  (
23:12:16   3    C1 NUMBER,
23:12:16   4    C2 CLOB
23:12:16   5  ) TABLESPACE TSUSER01 NOLOGGING LOB (C2) STORE AS BASICFILE;

Table created.

Elapsed: 00:00:00.17
23:12:16 SCOTT@ORCL> CREATE TABLE T1SF
23:12:20   2  (
23:12:20   3    C1 NUMBER,
23:12:20   4    C2 CLOB
23:12:20   5  ) TABLESPACE TSUSER01 NOLOGGING LOB (C2) STORE AS SECUREFILE;

Table created.

Elapsed: 00:00:00.10
23:12:21 SCOTT@ORCL> CREATE TABLE T1SF_CM
(23:12:25   2
23:12:25   3    C1 NUMBER,
23:12:25   4    C2 CLOB
23:12:25   5  ) TABLESPACE TSUSER01 NOLOGGING LOB (C2) STORE AS SECUREFILE CM (COMPRESS MEDIUM);

Table created.

Elapsed: 00:00:00.02
23:12:26 SCOTT@ORCL> CREATE TABLE T1SF_CH
23:12:29   2  (
23:12:29   3    C1 NUMBER,
23:12:29   4    C2 CLOB
23:12:29   5  ) TABLESPACE TSUSER01 NOLOGGING LOB (C2) STORE AS SECUREFILE CH (COMPRESS HIGH);

Table created.

Elapsed: 00:00:00.01
23:12:30 SCOTT@ORCL> CREATE TABLE T1SF_DD
23:12:34   2  (
23:12:34   3    C1 NUMBER,
23:12:34   4    C2 CLOB
23:12:34   5  ) TABLESPACE TSUSER01 NOLOGGING LOB (C2) STORE AS SECUREFILE DD (DEDUPLICATE);

Table created.

Elapsed: 00:00:00.01

23:16:30 SCOTT@ORCL> INSERT /*+ APPEND NOLOGGING */ INTO T1BF SELECT C1, C2 FROM SAMPLE;

11184 rows created.

Elapsed: 00:00:03.00
23:16:37 SCOTT@ORCL> COMMIT;

Commit complete.

Elapsed: 00:00:00.00
23:17:21 SCOTT@ORCL> INSERT /*+ APPEND NOLOGGING */ INTO T1SF SELECT * FROM T1BF UNION ALL SELECT * FROM T1BF;

22368 rows created.

Elapsed: 00:00:17.32
23:18:10 SCOTT@ORCL> INSERT /*+ APPEND NOLOGGING */ INTO T1SF_CM SELECT * FROM T1BF UNION ALL SELECT * FROM T1BF;

22368 rows created.

Elapsed: 00:00:06.37
23:18:44 SCOTT@ORCL> INSERT /*+ APPEND NOLOGGING */ INTO T1SF_CH SELECT * FROM T1BF UNION ALL SELECT * FROM T1BF;

22368 rows created.

Elapsed: 00:00:08.55
23:18:54 SCOTT@ORCL> INSERT /*+ APPEND NOLOGGING */ INTO T1SF_DD SELECT * FROM T1BF UNION ALL SELECT * FROM T1BF;

22368 rows created.

Elapsed: 00:00:21.86
23:19:17 SCOTT@ORCL> INSERT /*+ APPEND NOLOGGING */ INTO T1BF SELECT * FROM T1BF;

11184 rows created.

Elapsed: 00:00:02.83
23:19:21 SCOTT@ORCL> COMMIT;

Commit complete.

23:21:48 SCOTT@ORCL> @seg T1BF

OWNER      SEGMENT_NAME    PARTITION_NAME   SEGMENT_TYPE    TABLESPACE_NAME SIZE_MB
---------- --------------- ---------------- --------------- --------------- -------
SCOTT      T1BF                             TABLE           TSUSER01             21
SCOTT      SYS_IL000019428                  LOBINDEX        TSUSER01              0
           7C00002$$
SCOTT      SYS_LOB00001942                  LOBSEGMENT      TSUSER01            200
           87C00002$$


23:22:00 SCOTT@ORCL> @seg T1SF

OWNER      SEGMENT_NAME    PARTITION_NAME   SEGMENT_TYPE    TABLESPACE_NAME SIZE_MB
---------- --------------- ---------------- --------------- --------------- -------
SCOTT      T1SF                             TABLE           TSUSER01             21
SCOTT      SYS_IL000019429                  LOBINDEX        TSUSER01              0
           0C00002$$

SCOTT      SYS_LOB00001942                  LOBSEGMENT      TSUSER01            224
           90C00002$$


23:22:04 SCOTT@ORCL> @seg T1SF_CM

OWNER      SEGMENT_NAME    PARTITION_NAME   SEGMENT_TYPE    TABLESPACE_NAME SIZE_MB
---------- --------------- ---------------- --------------- --------------- -------
SCOTT      T1SF_CM                          TABLE           TSUSER01             19
SCOTT      CM                               LOBSEGMENT      TSUSER01              4
SCOTT      SYS_IL000019429                  LOBINDEX        TSUSER01              0
           3C00002$$


23:22:07 SCOTT@ORCL> @seg T1SF_CH

OWNER      SEGMENT_NAME    PARTITION_NAME   SEGMENT_TYPE    TABLESPACE_NAME SIZE_MB
---------- --------------- ---------------- --------------- --------------- -------
SCOTT      T1SF_CH                          TABLE           TSUSER01             15
SCOTT      CH                               LOBSEGMENT      TSUSER01              4
SCOTT      SYS_IL000019429                  LOBINDEX        TSUSER01              0
           6C00002$$


23:22:12 SCOTT@ORCL> @seg T1SF_DD

OWNER      SEGMENT_NAME    PARTITION_NAME   SEGMENT_TYPE    TABLESPACE_NAME SIZE_MB
---------- --------------- ---------------- --------------- --------------- -------
SCOTT      T1SF_DD                          TABLE           TSUSER01             21
SCOTT      DD                               LOBSEGMENT      TSUSER01            113
SCOTT      SYS_IL000019429                  LOBINDEX        TSUSER01              3
           9C00002$$

|

○ BFILE
Demo#5 (BFILE)
{code:sqlborderStyle=solid}
– OS 파일 포인터, 파일 읽기 모드 접근 가능, 읽기 일관성 없음
– SIZE : DIRECTORY 객체 이름, 파일 이름 + 오버헤드(20 바이트)
SQL> CREATE TABLE T
2 ( ID INT PRIMARY KEY,
3 OS_FILE BFILE
4 );

Table created.

SQL> CREATE OR REPLACE DIRECTORY MY_DIR AS '/tmp/';

Directory created.

SQL> INSERT INTO T VALUES (1, BFILENAME('MY_DIR', 'nofile'));

1 row created.

SQL> SELECT DBMS_LOB.GETLENGTH(OS_FILE) FROM T;
SELECT DBMS_LOB.GETLENGTH(OS_FILE) FROM T
*
ERROR at line 1:
ORA-22288: file or LOB operation GETLENGTH failed
No such file or directory
ORA-06512: at "SYS.DBMS_LOB", line 850

SQL> UPDATE T SET OS_FILE = BFILENAME('MY_DIR', 'testfile');

1 row updated.

SQL> SELECT DBMS_LOB.GETLENGTH(OS_FILE) FROM T;

DBMS_LOB.GETLENGTH(OS_FILE)







---
615698264

SQL> !du -sk /tmp/testfile
601268 /tmp/testfile

|