데이터베이스 연구실.log

세그먼트 공간 회수 (SHRINK, 지연된 세그먼트 생성)

SHRINK SPACE와 COMPACT의 조건, TRUNCATE의 공간 처리 및 지연된 세그먼트 생성

SHRINK SPACECOMPACTROW MOVEMENTHWMORA-10635ORA-10636DEFERRED_SEGMENT_CREATIONTRUNCATE REUSE STORAGE

#핵심 요약

DELETE는 블록 안을 비울 뿐 HWM(High Water Mark)을 내리지 않음
그래서 행을 많이 지워도 세그먼트 블록 수는 그대로임

세그먼트 축소(SHRINK SPACE)는 온라인, 제자리 작업임
ASSM 로컬 관리 테이블스페이스의 세그먼트에만 쓸 수 있고, 테이블은 행 이동(ENABLE ROW MOVEMENT)을 먼저 켜야 함

축소는 행을 앞으로 모으는 압축 단계와 HWM을 내리고 공간을 반환하는 단계로 나뉨
DML은 마지막 공간 반환 순간에만 잠깐 막힘
COMPACT를 주면 첫 단계만 하고 멈춤

지연된 세그먼트 생성(DEFERRED_SEGMENT_CREATION, 기본값 TRUE)이 켜져 있으면 CREATE TABLE 때는 세그먼트가 만들어지지 않고 첫 행이 들어올 때 만들어짐

#개념과 동작 원리

#세그먼트 축소

축소는 HWM 아래의 조각난 빈 공간을 회수함
데이터를 압축해 캐시 효율과 전체 테이블 스캔 성능이 좋아짐

데이터 이동 단계에서는 DML과 조회를 할 수 있고, 끝에 공간을 반환할 때 동시 DML이 잠깐 막힘

인덱스는 축소 중에도 유지되어 끝난 뒤 바로 쓸 수 있음
추가 디스크 공간이 필요 없음

행을 새 위치로 옮기므로 행 이동을 켜고, ROWID 기반 트리거가 있으면 꺼야 함

COMPACT를 주면 조각 모음과 행 압축만 하고 HWM 조정과 공간 반환은 미룸
결과가 디스크에 저장되므로 나중에 COMPACT 없이 다시 실행하면 이어서 끝냄

CASCADE를 주면 인덱스 같은 종속 세그먼트까지 함께 축소함

COMPACT 없이 축소하면 커서가 무효화되어 이후 SQL이 다시 파싱됨
종속 객체가 무효화될 수도 있음

구분 내용
축소할 수 있는 것 테이블, 인덱스 구조 테이블(IOT), 인덱스, 파티션, 서브파티션, 구체화 뷰, 구체화 뷰 로그
ASSM 안에서도 안 되는 것 IOT 매핑 테이블, ROWID 기반 구체화 뷰가 있는 테이블, 함수 기반 인덱스가 있는 테이블, SECUREFILE LOB, 기본 압축, 웨어하우스 압축, 아카이브 압축 테이블
수업 자료에만 있는 제외 대상 클러스터 안의 테이블, LONG 컬럼이 있는 테이블, 커밋 시점 구체화 뷰가 있는 테이블(SQL Language Reference와 미대조)

설명: 축소는 내부적으로 INSERT와 DELETE로 처리되지만 데이터 값은 바뀌지 않으므로 DML 트리거가 실행되지 않음
마이그레이션된 행이 줄 수는 있지만 모든 블록을 건드리지 않으므로 전부 없어진다고 보장할 수 없음
IOT를 축소한 뒤에는 보조 인덱스를 다시 만드는 것이 권장됨

#TRUNCATE와 공간

기본적으로 TRUNCATE는 MINEXTENTS로 정한 만큼을 빼고 지운 행이 쓰던 공간을 모두 반환함

DROP ALL STORAGE를 주면 세그먼트 전체를 지움(11.2.0.2부터)

실습: TRUNCATE ... REUSE STORAGE는 할당된 익스텐트를 그대로 두고, 옵션 없이 TRUNCATE하면 첫 익스텐트만 남음

#지연된 세그먼트 생성

DEFERRED_SEGMENT_CREATION은 기본값 TRUE이며 파티션이 없는 힙 테이블, 인덱스, 파티션에 적용됨

켜져 있으면 CREATE TABLE 때는 딕셔너리에 정의만 기록되고, 첫 행이 들어올 때 테이블, LOB, 인덱스 세그먼트가 함께 만들어짐

빈 테이블이 많은 애플리케이션 설치에서 디스크와 설치 시간을 아낌
세그먼트가 생기는 순간 그 테이블의 커서가 무효화되고, 나중에 데이터가 들어올 공간을 미리 계획해야 함

파라미터는 초기화 파일, ALTER SESSION, ALTER SYSTEM으로 바꿈
CREATE TABLE의 SEGMENT CREATION 절이 파라미터보다 우선함

인덱스 같은 종속 객체는 따로 정할 수 없고 부모 테이블 설정을 따름

실습 OCP 해설: IOT와 SYS 소유 테이블은 지연 생성을 지원하지 않음

#필수 명령어 또는 SQL

#DELETE 뒤에도 블록 수는 그대로

SQL*Plus (일반 사용자)데이터 또는 파일을 삭제함, 되돌릴 수 없음
CREATE TABLE emp_big AS SELECT * FROM emp;

BEGIN
  FOR i IN 1..10 LOOP
    INSERT INTO emp_big SELECT * FROM emp_big;
  END LOOP;
  COMMIT;
END;
/

DELETE FROM emp_big WHERE MOD(empno, 2) = 0;
COMMIT;
SQL*Plus (일반 사용자)조회만 함
SELECT COUNT(*) FROM emp_big;
SELECT blocks FROM user_segments WHERE segment_name = 'EMP_BIG';

결과 해석:

실습 예시값: 14,336행에서 10,240행을 지워 4,096행이 남았지만, BLOCKS는 삭제 전후 모두 72였음

#두 단계로 축소

SQL*Plus (일반 사용자)객체 또는 설정을 변경함
ALTER TABLE emp_big ENABLE ROW MOVEMENT;

ALTER TABLE emp_big SHRINK SPACE COMPACT;   -- 1단계: 행을 앞으로 모음, DML 막지 않음
ALTER TABLE emp_big SHRINK SPACE;           -- 2단계: HWM 조정과 공간 반환, 잠깐 DML 차단
SQL*Plus (일반 사용자)조회만 함
SELECT blocks FROM user_segments WHERE segment_name = 'EMP_BIG';

결과 해석:

실습 예시값: 72블록에서 41블록으로 줄었음
실습에서는 업무 시간에 COMPACT를 먼저 돌리고, 한가한 시간에 COMPACT 없이 다시 실행하라고 권함
공식 문서도 같은 사용법을 적음

#축소가 거부되는 두 경우

SQL*Plus (일반 사용자)데이터 또는 파일을 삭제함, 되돌릴 수 없음
CREATE TABLE shr_test AS SELECT * FROM all_objects WHERE ROWNUM <= 50000;
DELETE FROM shr_test WHERE MOD(object_id, 2) = 0;
COMMIT;

ALTER TABLE shr_test SHRINK SPACE;

결과 해석:

실습 기록: 행 이동을 켜지 않아 ORA-10636: ROW MOVEMENT is not enabled가 났음
기본 키나 고유 키가 없는 테이블이지만 행 이동을 켠 뒤에는 축소가 성공했음
제약 조건은 축소 조건이 아님

SQL*Plus (SYSDBA)객체 또는 설정을 변경함
CREATE TABLESPACE mssm_ts DATAFILE '<DATAFILE_DIR>/mssm01.dbf' SIZE 20M
  EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT MANUAL;
SQL*Plus (일반 사용자)객체 또는 설정을 변경함
CREATE TABLE shr_mssm TABLESPACE mssm_ts AS SELECT * FROM shr_test;
ALTER TABLE shr_mssm ENABLE ROW MOVEMENT;
ALTER TABLE shr_mssm SHRINK SPACE;

결과 해석:

실습 기록: 수동 세그먼트 공간 관리 테이블스페이스라서 ORA-10635: Invalid segment or tablespace type이 났음
실습의 다른 실습(OMF 절)에서도 같은 오류를 기록했음

#COMPACT만 했을 때의 상태

SQL*Plus (일반 사용자)조회만 함
SELECT blocks FROM user_segments WHERE segment_name = 'ORD_TEST';
SELECT MAX(DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)) AS max_blk FROM ord_test;
SELECT status FROM user_indexes WHERE index_name = 'ORD_TEST_I';

결과 해석:

실습에서는 ALL_OBJECTS를 두 배로 복사한 ORD_TEST에서 4분의 3을 지운 뒤, SHRINK SPACE COMPACT 앞뒤로 위 조회를 했음

시점 BLOCKS MAX_BLK(가장 뒤 행의 블록 번호) 인덱스 STATUS
축소 전 4224 4198 VALID
COMPACT 뒤 4224 1056 VALID
COMPACT 없이 다시 축소한 뒤 1088 기재 없음 기재 없음

행은 앞으로 모였지만 COMPACT만으로는 HWM과 블록 수가 그대로이고, 인덱스는 계속 VALID임

#지연된 세그먼트 생성 확인

SQL*Plus (일반 사용자)조회만 함
SELECT name, value, isses_modifiable, issys_modifiable
  FROM v$parameter
 WHERE name = 'deferred_segment_creation';

결과 해석:

설명: VALUE는 TRUE, ISSES_MODIFIABLE은 TRUE로 나와 세션 단위로 바꿀 수 있음

SQL*Plus (일반 사용자)객체 또는 설정을 변경함
CREATE TABLE seg_immediate (id NUMBER, name VARCHAR2(20))
  SEGMENT CREATION IMMEDIATE TABLESPACE users;

CREATE TABLE seg_deferred (id NUMBER, name VARCHAR2(20))
  SEGMENT CREATION DEFERRED TABLESPACE users;
SQL*Plus (일반 사용자)조회만 함
SELECT segment_name, segment_type, bytes/1024 AS kb
  FROM user_segments
 WHERE segment_name IN ('SEG_IMMEDIATE', 'SEG_DEFERRED');

SELECT table_name, segment_created
  FROM user_tables
 WHERE table_name IN ('SEG_IMMEDIATE', 'SEG_DEFERRED');

결과 해석:

설명: 첫 조회에는 SEG_IMMEDIATE만 나오고, SEGMENT_CREATED는 각각 YES와 NO임
SEG_DEFERRED에 한 행을 넣고 커밋하면 첫 조회에 함께 나타남
기본 키와 CLOB이 있는 테이블은 CREATE 직후 세그먼트가 하나도 없다가, 첫 행이 들어오면 테이블, 기본 키 인덱스, LOB, LOB 인덱스 네 개가 한꺼번에 생김
일반 계정은 USERS 테이블스페이스 Quota가 필요함

#사용 조건과 주의사항

실습 축소 확인 문제의 풀이는 employees를 대상으로 하면서 2단계 명령만 emp_big에 실행함
대상 이름이 섞인 것으로 보임

마이그레이션된 행을 없애는 방법(ALTER TABLE ... MOVE)은 행 체이닝과 마이그레이션에서 다룸

SEO_HKabsumveritas@gmail.comBuilt with Claude Code & Codex

마지막 갱신 개인 학습 기록이며 운영 환경 적용 전 공식 문서 확인 필요

두 글자 이상 입력, 위아래 화살표로 이동하고 Enter로 열기