기술 정보
home
채널 소개
home

TABLE REORG 대상 조회 방법과 REORG 수행 방법

문서 유형
기술 정보
분야
모니터링/점검
키워드
REORG
Online Reorg
1 more property

개요

본 글에서는 TABLE REORG 대상 테이블을 조회하는 방법실제 REORG 작업을 수행하는 예시 쿼리를 함께 설명합니다.

방법

REORG 대상 조회 방법

각 TABLE 이 차지하고 있는 사이즈와 예상되는 테이블 사이즈를 비교해 비율 차이가 많이 나는 테이블을 대상으로 DBMS_SPACE 패키지로 REORG 대상 조회 작업을 합니다.
(row count * row max length) / (table block count * block size)
SQL
복사

1. DBMS_SPACE 체크 대상 조회 쿼리

테이블의 extents 된 사이즈와 예상 테이블 사이즈의 차이가 100MB 초과와 예상 테이블 사이즈/extents 된 사이즈의 비율이 50% 이하일 경우 조회합니다.
조회 쿼리는 통계정보 수집한 테이블을 대상으로 확인합니다.
SET LINES 180; COL owner FOR A10; COL table_name FOR A30; SELECT * FROM ( SELECT a.owner, b.table_name, table_type, last_analyzed, num_rows, ROUND(extents_size / 1024 / 1024, 2) AS "EXTENTS_SIZE(MB)", ROUND(max_data_size / 1024 / 1024, 2) AS "MAX_DATA_SIZE(MB)", ROUND((extents_size - max_data_size) / 1024 / 1024, 2) AS "DIFF_SIZE(MB)", ROUND((max_data_size / extents_size * 100), 2) AS "DATA_RATE(%)" FROM ( SELECT owner, segment_name, SUM(bytes) AS extents_size, -- table extents total size SUM(blocks) AS extents_block_count -- table extents block total count FROM dba_extents WHERE owner NOT IN ('SYS', 'SYSCAT', 'SYSGIS') AND segment_type IN ('TABLE', 'TABLE PARTITION') GROUP BY owner, segment_name ) a, ( SELECT a.owner, a.table_name, DECODE(partitioned, 'YES', 'PARTITION TABLE', 'TABLE') AS table_type, last_analyzed, ROUND(num_rows) AS num_rows, blocks, avg_row_len, max_row_len, (ROUND(num_rows) * max_row_len) AS max_data_size FROM dba_tables a, ( SELECT owner, table_name, SUM(data_length) AS max_row_len -- 1 row max size FROM dba_tbl_columns WHERE owner NOT IN ('SYS', 'SYSCAT', 'SYSGIS') GROUP BY owner, table_name ) b WHERE a.owner = b.owner AND a.table_name = b.table_name AND last_analyzed IS NOT NULL ) b WHERE a.owner = b.owner AND a.segment_name = b.table_name ) x WHERE "DIFF_SIZE(MB)" > 100 AND "DATA_RATE(%)" < 50 ORDER BY "DATA_RATE(%)" DESC, "DIFF_SIZE(MB)" DESC;
SQL
복사

2. REORGE 대상 조회 쿼리

1 번에서 조회된 테이블을 대상으로 데이터 블록 사용량 확인해서 REORG 필요 여부 확인합니다.
in 조건안에 조회 대상 테이블 입력후 조회합니다.
FREE 비율이 50% 이상인 블록이 전체 블록의 20% 초과시 REORG 대상으로 선정합니다.
SET SERVEROUTPUT ON SET LINESIZE 180 SET PAGESIZE 100 DECLARE USED_BLOCKS NUMBER; FRM_BLOCKS NUMBER; FRM_RATIO NUMBER; uf NUMBER; ub NUMBER; f1 NUMBER; f1b NUMBER; f2 NUMBER; f2b NUMBER; f3 NUMBER; f3b NUMBER; f4 NUMBER; f4b NUMBER; fbl NUMBER; fby NUMBER; BEGIN FOR tb_list IN ( SELECT owner, segment_name, partition_name, segment_type FROM dba_segments WHERE segment_name IN ('MK_TBH_RF_COV','TEST','ABC') -- 조회 대상 테이블 ) LOOP BEGIN dbms_space.space_usage( tb_list.owner, tb_list.segment_name, tb_list.segment_type, uf, ub, f1, f1b, f2, f2b, f3, f3b, f4, f4b, fbl, fby, tb_list.partition_name ); USED_BLOCKS := f1 + f2 + f3 + f4 + fbl; FRM_BLOCKS := f3 + f4; IF USED_BLOCKS = 0 THEN dbms_output.put_line('----------------------'); dbms_output.put_line(tb_list.owner || '.' || tb_list.segment_name || '.' || tb_list.partition_name || ' is not used.'); ELSE FRM_RATIO := ROUND(FRM_BLOCKS / USED_BLOCKS * 100); IF USED_BLOCKS > 100 THEN IF FRM_RATIO > 20 THEN dbms_output.put_line('#######################'); dbms_output.put_line(tb_list.owner || '.' || tb_list.segment_name || '.' || tb_list.partition_name || ' is fragmented ' || FRM_RATIO || '%'); dbms_output.put_line('unformatted blocks : ' || TO_CHAR(uf)); dbms_output.put_line('blocks 0-25% free : ' || TO_CHAR(f1)); dbms_output.put_line('blocks 25-50% free : ' || TO_CHAR(f2)); dbms_output.put_line('blocks 50-75% free : ' || TO_CHAR(f3)); dbms_output.put_line('blocks 75-100% free : ' || TO_CHAR(f4)); dbms_output.put_line('full blocks : ' || TO_CHAR(fbl)); ELSE dbms_output.put_line('----------------------'); dbms_output.put_line(tb_list.owner || '.' || tb_list.segment_name || '.' || tb_list.partition_name || ' is fragmented [' || FRM_RATIO || '%]'); END IF; ELSE dbms_output.put_line('----------------------'); dbms_output.put_line(tb_list.owner || '.' || tb_list.segment_name || '.' || tb_list.partition_name || ' pass [' || USED_BLOCKS || '] Used blocks'); END IF; END IF; EXCEPTION WHEN OTHERS THEN dbms_output.put_line(TO_CHAR(SQLCODE) || ':' || SQLERRM); END; END LOOP; END; /
SQL
복사

Online REORGE 방법 (Table Shrink)

1. 대상 테이블과 동일한 구조를 가진 임시 테이블 생성

CREATE TABLE temp_table ( column, ... );
SQL
복사

2. Redefinition 작업 시작

BEGIN DBMS_REDEFINITION.START_REDEF_TABLE( UNAME => 'owner', ORIG_TABLE => 'target_table', INT_TABLE => 'temp_table', OPTIONS_FLAG => 2); -- 1: PK 정보 사용, 2: ROWID 정보 사용 (Default: 1) END; /
SQL
복사

3. Redefinition 완료 후 임시 테이블에 PRIMARY KEY 및 인덱스 추가

1) PRIMARY KEY 추가
ALTER TABLE temp_table ADD CONSTRAINT pk_constraint_name PRIMARY KEY(column);
SQL
복사
2) 인덱스 추가
CREATE INDEX temp_index ON temp_table ( column, ... );
SQL
복사

4. Redefinition 작업 도중 발생한 변경 데이터 Sync 작업 진행

BEGIN DBMS_REDEFINITION.SYNC_INTERIM_TABLE( UNAME => 'owner', ORIG_TABLE => 'target_table', INT_TABLE => 'temp_table'); END; /
SQL
복사

5. 임시 테이블과 대상 테이블의 변경

BEGIN DBMS_REDEFINITION.FINISH_REDEF_TABLE( UNAME => 'owner', ORIG_TABLE => 'target_table', INT_TABLE => 'temp_table'); END; /
SQL
복사

6. 제약사항 및 인덱스 이름 변경

1) 인덱스 이름 변경
temp_table 의 인덱스 이름을 변경한 후 target_table 의 인덱스 이름을 변경합니다.
ALTER INDEX temp_index RENAME TO index_name;
SQL
복사
2) 제약사항 이름 변경
temp_table 의 PRIMARY KEY 등의 제약사항 이름을 변경한 후 target_table 의 제약사항 이름을 변경합니다.
ALTER TABLE TEST RENAME CONSTRAINT PK_TEST_BAK TO PK_TEST;
SQL
복사

7. 임시 테이블 drop

DROP TABLE temp_table;
SQL
복사