I. 테스트 환경 구성
1. 스키마 생성 및 권한 부여
테스트 스키마 생성 및 권한 부여
create tablesapce TEST datafile '+DATA' size 3G; create user TEST identified by TEST default tablespace TEST; grant CONNECT, RESOURCE, UNLIMITED TABLESPACE to TEST;
2. 테스트용 원본 테이블 생성
A) 원본 테이블 생성
테스트용 원본 테이블 생성
create table TEST.YKTEST ( BASE_DT varchar2(8) not null, TESTCOL1 varchar2(20) not null, TESTCOL2 number not null, TESTCOL3 char(20) not null, TESTCOL4 varchar2(20), TESTCOL5 char(20), TESTCOL6 nchar(20), TESTCOL7 varchar2(20), TESTCOL8 varchar2(20), TESTCOL9 varchar2(20), constraint PK_YKTEST primary key (BASE_DT,TESTCOL1,TESTCOL2) ) tablespace USERS; -- 초기 데이터는 USERS에 적재
B) 랜덤 데이터 입력
랜덤 데이터 입력
insert into TEST.YKTEST select to_char(sysdate-dbms_random.value(0,365*7),'RRRRMMDD') as BASE_DT, dbms_random.string('A',20) as TEST_COL1, dbms_random.value(0,1000) as TEST_COL2, dbms_random.string('A',20) as TEST_COL3, dbms_random.string('A',20) as TEST_COL4, dbms_random.string('A',20) as TEST_COL5, NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) || -- 2 NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) || -- 4 NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) || -- 6 NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) || -- 8 NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) || -- 10 NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) || -- 12 NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) || -- 14 NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) || -- 16 NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) || -- 18 NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) as TEST_COL6, --20 dbms_random.string('A',20) as TEST_COL7, dbms_random.string('A',2) || -- 2 NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) || -- 8 NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) || -- 14 NCHR(dbms_random.value(44032, 55203)) || NCHR(dbms_random.value(44032, 55203)) as TEST_COL8, --20 dbms_random.string('A',20) as TEST_COL9 from DUAL connect by level <= 5000000; -- 메모리 부족 발생시 1000000건으로 5번 수행
II. 테이블 파티셔닝
1. 사전 준비
A) 세션 병렬 처리 설정
세션 병렬 처리 설정
alter session enable parallel ddl; alter session enable parallel dml; alter session force parallel dml parallel 8; alter session force parallel ddl parallel 8; alter session force parallel query parallel 8;
B) 작업 가능 여부 확인
Redefinition 가능 여부 체크
exec DBMS_REDEFINITION.CAN_REDEF_TABLE('TEST', 'YKTEST',dbms_redefinition.cons_use_pk); -- PK가 없을 경우 dbms_redefinition.cons_use_rowid 옵션 사용
C) Interim 파티션 테이블 생성
2. Redefinition 수행
A) Redefinition 시작
Redefinition 시작
exec DBMS_REDEFINITION.START_REDEF_TABLE('TEST','YKTEST','YKTEST_PT'); -- Interim 파티션 테이블에 데이터 적재 시작
B) 작업 모니터링
select * from V$ONLINE_REDEF;
C) 데이터 동기화
Redefinition 싱크
exec DBMS_REDEFINITION.SYNC_INTERIM_TABLE('TEST','YKTEST','YKTEST_PT'); -- 온라인 작업으로 중간에 데이터 변경이 많을 경우 수행
D) PK 제약조건 생성
Interim 파티션 테이블에 PK 파티션 인덱스 및 제약조건 생성
create unique index TEST.PK_YKTEST_PT on TEST.YKTEST_PT (BASE_DT,TESTCOL1,TESTCOL2) local parallel 8 nologging; alter table TEST.YKTEST_PT add constraint PK_YKTEST_PT primary key (BASE_DT,TESTCOL1,TESTCOL2) using index; -- 데이터 동기화 및 검증을 위해 PK 생성이 먼저 필요하며, 수동으로 생성하지 않을 경우 시스템이 동기화를 위해 임의로 PK를 생성해버림 -- 동일한 이름의 PK 인덱스를 사용할 수 없어서, 임시로 "파티션 PK 인덱스명"으로 생성 (작업 종료 시점에 rename 예정)
E) 기타 제약조건 복사
제약조건 복사 (SQL*Plus에서 실행)
set serveroutput on -- -- copy_indexes = no => 인덱스는 파티션으로 수동 생성해야 하므로 제외 -- copy_trigger = yes -- copy_constraints = yes -- copy_privileges=yes -- ignore_error = yes -- copy_statistics = no -- DECLARE num_errors PLS_INTEGER; BEGIN DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('TEST','YKTEST','YKTEST_PT',0,TRUE,TRUE,TRUE,TRUE,num_errors,FALSE); dbms_output.put_line('Error : '||num_errors); end; / set serveroutput on DECLARE num_errors PLS_INTEGER; BEGIN DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS( uname=>'TEST', orig_table=>'YKTEST', int_table=>'YKTEST_PT', copy_indexes=>0, copy_triggers=>TRUE, copy_constraints=>TRUE, copy_privileges=>TRUE, ignore_errors=>TRUE, num_errors=>num_errors, copy_statistics=>FALSE); dbms_output.put_line('Error : '||num_errors); end; / -- PK와 Not Null 조건이 이미 생성되어 오류 건수 검출 예정
F) 에러 확인
제약조건 복제 에러 확인
select object_name, base_table_name, ddl_txt from DBA_REDEFINITION_ERRORS;
G) PK 관련 이름 변경
PK 인덱스, 제약조건 이름 변경
alter index TEST.PK_YKTEST rename to PK_YKTEST_BK; alter index TEST.PK_YKTEST_PT rename to PK_YKTEST; alter index TEST.PK_YKTEST logging; alter table TEST.YKTEST rename constraint PK_YKTEST to PK_YKTEST_BK; alter table TEST.YKTEST_PT rename constraint PK_YKTEST_PT to PK_YKTEST;
3. 작업 종료
A) Redefiniton 종료
Redefinition 종료
exec DBMS_REDEFINITION.FINISH_REDEF_TABLE('TEST','YKTEST','YKTEST_PT');
B) 파티션 테이블 모드 변경
파티션 테이블 logging 모드 변경
alter table TEST.YKTEST_PT logging;
III. 실패시 정리 방법
exec DBMS_REDEFINITION.ABORT_REDEF_TABLE('TEST','YKTEST','YKTEST_PT');
기술 메모
- Interim 테이블 가공을 통해 테이블 구조 변경 가능 (interim 테이블 : 작업 단계에서 데이터를 적재하는 테이블로, 최종 단계에서 원본 테이블로 교체됨)
: 컬럼 순서 변경 가능. 동일한 컬럼명 사용 필수
: 컬럼 크기 확장 가능. 컬럼 크기 축소 불가능 ex) varchar2(20) => varchar2(40) - START_REDEF_TABLE 수행시 MLOG$_<테이블명>, RUPD$_<테이블명>의 테이블이 생성되나 세그먼트는 할당되지 않음
: 원본 테이블과 interim 테이블간의 동기화를 위해 변경 데이터를 체크하기 위한 용도로 생성됨 - START_REDEF_TABLE 이후에 insert된 데이터는 임시 세그먼트에 저장됨
: 파티션 테이블을 새로운 테이블스페이스에 만들었더라도, 임시 세그먼트는 기존 테이블이 있던 테이블스페이스에 임시로 저장됨
: SYNC_INTERIM_TABLE를 수행하면 임시 세그먼트에 있던 내용이 파티션 테이블(interim 테이블)로 옮겨 저장됨 - START_REDEF_TABLE 이후 데이터 변경이 많지 않다면 SYNC_INTERIM_TABLE 없이 FINISH_REDEF_TABLE를 수행하면 시간 절약 가능
: SYNC_INTERIM_TABLE와 FINISH_REDEF_TABLE를 수행할 때마다 변경 데이터를 검증하는데 시간이 소요되는 것으로 보임 - 반드시 PK를 local partition 인덱스로 수동 생성해야 함. PK 제약조건 또한 수동으로 추가하는 것을 권장함
: COPY_TABLE_DEPENDENTS 로 인덱스를 복제할 경우, 기존 테이블의 인덱스 구조로 파티션이 안된 인덱스가 생성됨
: PK 인덱스만 파티션으로 수동으로 생성하고, COPY_TABLE_DEPENDENTS 로 PK 제약조건을 복사하면 FINISH_REDEF_TABLE 단계에서 인덱스와 제약조건의 이름이 같지 않아 오류가 발생함
: 오류 예방을 최소화하고자 PK 작업은 모두 수동으로 하는 것을 권장함