[2025-07-05] 비파티션 테이블을 파티션 테이블로 온라인 전환 (12cR2 New features) (12cR2에서 테스트)
[실습
환경]
OS
: Oracle Linux Server 7.9 (Linux 5.4.17-2102.201.3.el7uek.x86_64)
DB : Oracle
Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit
Production
(Database Jan 2022 Release Update :
12.2.0.1.220118 (33587128))
RAC1 : rdb01p(192.168.0.11) : PRDB1
RAC2 :
rdb02p(192.168.0.12) : PRDB2
이것은 오라클
12.2 릴리스의 새로운 기능 중 하나임
비 파티션 테이블을 애플리케이션 다운타임 없이 온라인으로 파티션 테이블로 변환할 수 있으며, 이는
DML 활동에 영향을 미치지 않음
지금까지 이 활동에서는 DBMS_REDEFINITION 패키지를
사용했었음
하지만 Oracle 12.2 버전에서는 이 작업이 훨씬 간소화됨
1. 테스트 테이블 생성 (비파티션 테이블 생성)
DROP TABLE
TUNER.TB_ORD_NON_PART PURGE;
CREATE TABLE
TUNER.TB_ORD_NON_PART
(
CUST_NO VARCHAR2(10) NOT NULL
, ORD_DT
VARCHAR2(14) NOT NULL
, ORD_TOT_AMT NUMBER(15, 2) NOT NULL
, ORD_STS_CD
VARCHAR2(6) NOT NULL
, INPUT_ID VARCHAR2(20) NOT NULL
, INPUT_DT
VARCHAR2(14) NOT NULL
, UPDT_ID VARCHAR2(20)
, UPDT_DT
VARCHAR2(14)
)
TABLESPACE TUNER_DATA1
;
ALTER TABLE
TUNER.TB_ORD_NON_PART NOLOGGING;
INSERT INTO
TUNER.TB_ORD_NON_PART SELECT * FROM
TUNER.TB_ORD;
COMMIT;
ALTER TABLE TUNER.TB_ORD_NON_PART LOGGING;
CREATE
UNIQUE INDEX TUNER.PK_TB_ORD_NON_PART
ON TUNER.TB_ORD_NON_PART
(CUST_NO,ORD_DT)
TABLESPACE TUNER_IDX1;
ALTER TABLE
TUNER.TB_ORD_NON_PART
ADD CONSTRAINT PK_TB_ORD_NON_PART PRIMARY KEY
(CUST_NO,ORD_DT);
BEGIN
DBMS_STATS.GATHER_TABLE_STATS
(
OWNNAME =>
'TUNER'
,
TABNAME =>
'TB_ORD_NON_PART'
, ESTIMATE_PERCENT =>
DBMS_STATS.AUTO_SAMPLE_SIZE
,
GRANULARITY => 'ALL' --'ALL' - Gathers all
(subpartition, partition, and global) statistics
,
CASCADE =>
TRUE
,
METHOD_OPT => 'FOR ALL COLUMNS SIZE
1'
,
DEGREE =>
1
, NO_INVALIDATE => TRUE --TRUE: Dependent
cursors are not invalidated, FALSE: Dependent cursors are marked for immediate
invalidation
);
END;
/
TB_ORD_NON_PART
---------------
Rows=10,000,000
Blocks=100,877
Empty_Blocks=0
Avg_Space=0
Chain_Count=0
Avg_Row_Length=67
Avg_Space_Freelist_Blocks=0
Freelist_Blocks=0
Sample_Size=10,000,000
Last_Analyzed='2025/07/06
00:33:26'
Partitioned='NO'
Tablespace='TUNER_DATA1'
Column
Name
Nullable Column Type
Distinct Buckets
--------------------------------
-------- ------------------- ---------- ----------
CUST_NO
NOT NULL
VARCHAR2(10)
995,520 1
ORD_DT
NOT NULL VARCHAR2(14)
9,878,528 1
ORD_TOT_AMT
NOT NULL
NUMBER(15,2)
447 1
ORD_STS_CD
NOT NULL
VARCHAR2(6)
4 1
INPUT_ID
NOT NULL VARCHAR2(20)
10,000,000 1
INPUT_DT
NOT NULL
VARCHAR2(14)
1 1
UPDT_ID
VARCHAR2(20)
0 0
UPDT_DT
VARCHAR2(14)
0 0
INDEX
-----------------------------------------------------------------------------
PK_TB_ORD_NON_PART : CUST_NO,ORD_DT
Type='NORMAL',
Uniq='YES', Distinct=10,300,810, Rows=10,300,810, Last_Analyzed='2025/07/06
00:33:29'
2. ONLINE으로 비파티션 테이블을 파티션 테이블로 전환
ALTER TABLE
TUNER.TB_ORD_NON_PART MODIFY PARTITION BY RANGE (ORD_DT)
(
PARTITION P_BEF_2020 VALUES LESS THAN ('20200101') TABLESPACE TUNER_DATA1
NOCOMPRESS
, PARTITION P2020 VALUES LESS THAN
('20210101') TABLESPACE TUNER_DATA1 NOCOMPRESS
, PARTITION
P2021 VALUES LESS THAN ('20220101') TABLESPACE
TUNER_DATA1 NOCOMPRESS
, PARTITION P2022 VALUES
LESS THAN ('20230101') TABLESPACE TUNER_DATA1 NOCOMPRESS
, PARTITION
P2023 VALUES LESS THAN ('20240101') TABLESPACE
TUNER_DATA1 NOCOMPRESS
, PARTITION P2024 VALUES
LESS THAN ('20250101') TABLESPACE TUNER_DATA1 NOCOMPRESS
, PARTITION
P2025 VALUES LESS THAN ('20260101') TABLESPACE
TUNER_DATA1 NOCOMPRESS
, PARTITION P2026 VALUES
LESS THAN ('20270101') TABLESPACE TUNER_DATA1 NOCOMPRESS
, PARTITION
P2027 VALUES LESS THAN ('20280101') TABLESPACE
TUNER_DATA1 NOCOMPRESS
, PARTITION P2028 VALUES
LESS THAN ('20290101') TABLESPACE TUNER_DATA1 NOCOMPRESS
, PARTITION
P2029 VALUES LESS THAN ('20300101') TABLESPACE
TUNER_DATA1 NOCOMPRESS
, PARTITION P2030 VALUES
LESS THAN ('20310101') TABLESPACE TUNER_DATA1 NOCOMPRESS
, PARTITION
P_AFT_2033 VALUES LESS THAN (MAXVALUE) TABLESPACE TUNER_DATA1
NOCOMPRESS
)
ONLINE;
--> 해당 작업 시 인덱스 관련 옵션을 주지 않을 경우 인덱스는
-->
인덱스 구성 칼럼에 파티션 키가 속하는 경우는 LOCAL PARTITION INDEX로 만들어진다.
(예 : 인덱스가
CUST_NO+ORD_DT인 경우 파티션 키인 ORD_DT가 인덱스 구성 칼럼에 포함되므로 LOCAL 파티션 인덱스로 생성됨)
-->
그렇지 않으면 GLOBAL NON-PARTITION INDEX로 만들어진다.
--> 인덱스 관련 옵션은 아래와 같이 주면됨
(인덱스 글로벌로 할지 LOCAL로 할지 지정가능)
UPDATE INDEXES
(
<인덱스명> GLOBAL
, <인덱스명> LOCAL
);
--작업 중 새로운
세션을
열어서-------------------------------------------------------
UPDATE TUNER.TB_ORD_NON_PART SET
UPDT_ID = '1' WHERE CUST_NO = 'C000001961';
DELETE TUNER.TB_ORD_NON_PART
WHERE CUST_NO = 'C000001961';
--> DML작업이
가능함
ROLLBACK;
-------------------------------------------------------------------------------------
TB_ORD_NON_PART
---------------
Rows=10,000,000
Blocks=100,877
Empty_Blocks=0
Avg_Space=0
Chain_Count=0
Avg_Row_Length=67
Avg_Space_Freelist_Blocks=0
Freelist_Blocks=0
Sample_Size=10,000,000
Last_Analyzed='2025/07/06 00:33:26'
Partitioned='YES'
Column
Name
Nullable Column Type
Distinct Buckets
--------------------------------
-------- ------------------- ---------- ----------
CUST_NO
NOT NULL
VARCHAR2(10)
995,520 1
ORD_DT
NOT NULL VARCHAR2(14)
9,878,528 1
ORD_TOT_AMT
NOT NULL
NUMBER(15,2)
447 1
ORD_STS_CD
NOT NULL
VARCHAR2(6)
4 1
INPUT_ID
NOT NULL VARCHAR2(20)
10,000,000 1
INPUT_DT
NOT NULL
VARCHAR2(14)
1 1
UPDT_ID
VARCHAR2(20)
0 0
UPDT_DT
VARCHAR2(14)
0 0
Table Partition
-----------------------------------------------------------------------------
Type = Range Partition
Keys = ORD_DT
INDEX
-----------------------------------------------------------------------------
PK_TB_ORD_NON_PART : CUST_NO,ORD_DT
Partition=LOCAL
NON_PREFIXED
Type='NORMAL', Uniq='YES',
Distinct=1,005,198, Rows=10,000,000, Last_Analyzed='2025/07/06
00:40:14'
--테이블 메타 데이터 출력하는 법 (최종 확인 시 사용)
BEGIN
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,
'TABLESPACE', true);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,
'STORAGE', true);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,
'SEGMENT_ATTRIBUTES', true);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,
'CONSTRAINTS', true);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,
'REF_CONSTRAINTS', false);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,
'SQLTERMINATOR', true);
dbms_metadata.set_transform_param(dbms_metadata.session_transform, 'PRETTY',
true);
END;
/
SELECT DBMS_METADATA.GET_DDL('TABLE',
'TB_ORD_NON_PART', 'TUNER') FROM DUAL;
SELECT DBMS_METADATA.GET_DDL('INDEX',
INDEX_NAME, 'TUNER') FROM DBA_INDEXES WHERE TABLE_OWNER = 'TUNER' AND TABLE_NAME
= 'TB_ORD_NON_PART';
SELECT DBMS_METADATA.GET_DDL('CONSTRAINT',
CONSTRAINT_NAME, 'TUNER') FROM DBA_CONSTRAINTS WHERE OWNER = 'TUNER' AND
TABLE_NAME = 'TB_ORD_NON_PART';