본문 바로가기
Tibero/Tibero6

신규기능 - Partition Exchange

by dan.de.lion 2017. 1. 5.

신규 기능 - Partition Exchange


Partition Exchange

테스트 환경

OS : OEL release 7.2
Tibero : 6 FS05

Partition Exchange


  • Partition Exchange 기능은 PartitionExchange 하는 기능이다. (이런건 이제 익숙하다)
  • 우선, Partition이란 Partitioned Table에서 하나의 독립된 공간을 의미하며
    Exchange는 말 그대로 “맞바꿈”을 의미한다.
  • 또한, 여기서 “맞바꿈”의 대상이 되는 공간은 Non-Partitioned Table이다.
  • 즉, Partitioned Table에서 하나의 독립된 공간과 Non-Partitioned Table을 “맞바꾸는” 기능이다.
  • 해당 기능을 통해 Partitioned TableNon-Partitioned Table로 변경하거나
    Non-Partitioned Table(이하 Table)을 Partitioned Table로 변경할 수 있다.

기능 테스트


  • Table을 변경하는 작업으로 ALTER TABLE1을 기본구문으로 한다.

Partition Exchange 기본 구문


  • TablePartition을 상호교체 시 기본적으로 Partition key에 위배되는 값이 있는지 검증하게 된다.
    (WITH VALIDATION으로 동작한다.)
  • WITHOUT VALIDATION 옵션 적용 시 위의 검증단계가 생략된다.
    (검증단계가 생략되는 만큼 빠르다.)
  • Partitioned TableTable 어느 쪽이라도 Index가 있는 경우
    반대쪽 Table에도 동일한 ColumnIndex모두 생성해야 한다.
  • 즉, 모든 Index key Column을 동일하게 맞춰야 한다.
  • 다만, 교체하게 되면 인덱스가 UNUSABLE 상태가 된다.
    (위 두 가지 경우를 회피하기 위한 파라미터가 5에는 Hidden으로 존재한다.)
  • 따라서, 경우에 따라 삭제 후 재생성이 빠를 수 있다.
  • 해당 구문은 아래와 같다.
SQL> ALTER TABLE table_name                    -- Partitioned Table 명시
     EXCHANGE
       PARTITION|SUBPARTITION partition_name   -- 해당 Partition 명시
       WITH TABLE table_name                   -- Non-Partitioned Table 명시
      [WITH|WITHOUT VALIDATION]                -- 검증 여부(생략시 검증 수행)
     ;

Test 사전 준비


  • Partitioned Table 생성하고 데이터를 적재한다.
SQL> /* Partitioned Table 생성(TEST_PART) */
SQL> CREATE TABLE TEST_PART
     (A NUMBER,
      B NUMBER,
      C VARCHAR(100),
      D DATE)
     NOLOGGING
     PARTITION BY RANGE (A)
     (PARTITION PART_01 VALUES LESS THAN (1),
      PARTITION PART_02 VALUES LESS THAN (2),
      PARTITION PART_03 VALUES LESS THAN (3),
      PARTITION PART_04 VALUES LESS THAN (4))
     ;

Table 'TEST_PART' created.

SQL> /* 데이터 적재 */
SQL> INSERT INTO TEST_PART
     SELECT MOD(LEVEL,4) A,
         LEVEL B,
         DBMS_RANDOM.STRING('X',100) C,
         TO_DATE(SYSDATE + LEVEL/24/60/60) D
     FROM DUAL
     CONNECT BY LEVEL < 1000000
     ;

999999 rows inserted.

SQL> COMMIT;

Commit completed.

-Local Partitioned Index를 생성한다.

SQL> /* Local Partitioned Index 생성 */
SQL> CREATE INDEX TEST_PART_IDX ON TEST_PART (A,B) LOCAL NOLOGGING ;

Index 'TEST_PART_IDX' created.
  • Talbe을 생성하고 데이터를 적재 및 Index를 생성한다.
SQL> /* Non-Partitioned Table 생성
      - 교체할 PART_02 Partition의 데이터를 적재 */
SQL> CREATE TABLE TEST_NON
     TABLESPACE USR2
     AS
     SELECT * FROM TEST_PART PARTITION(PART_02)
      WHERE B < 500000
     ;

Table 'TEST_NON' created.

SQL> /* Index 생성 */
SQL> CREATE INDEX TEST_NON_IDX ON TEST_NON (A,B) TABLESPACE USR2 ;

Index 'TEST_NON_IDX' created.
  • 생성된 TableIndex의 정보를 조회한다.
SQL> /* 정보 조회 */
SQL> -- SEGMENT별 Tablespace 정보
SQL> SELECT SEGMENT_NAME, PARTITION_NAME, TABLESPACE_NAME
       FROM USER_SEGMENTS
      ORDER BY 1, 2
     ;

SEGMENT_NAME         PARTITION_NAME        TABLESPACE_NAME     
-------------------- --------------------- --------------------
TEST_NON                                   USR2
TEST_NON_IDX                               USR2
TEST_PART            PART_01               USR
TEST_PART            PART_02               USR
TEST_PART            PART_03               USR
TEST_PART            PART_04               USR
TEST_PART_IDX        PART_01               USR
TEST_PART_IDX        PART_02               USR
TEST_PART_IDX        PART_03               USR
TEST_PART_IDX        PART_04               USR

10 rows selected.

SQL> -- Index 상태 조회
SQL> SELECT INDEX_NAME, STATUS
       FROM USER_INDEXES
      ORDER BY 1
     ;

INDEX_NAME            STATUS  
--------------------- --------
TEST_NON_IDX          VALID
TEST_PART_IDX         VALID

2 rows selected.

SQL> -- Index Partition 상태 조회
SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
       FROM USER_IND_PARTITIONS
      ORDER BY 1, 2
     ;

INDEX_NAME            PARTITION_NAME        STATUS  
--------------------- --------------------- --------
TEST_PART_IDX         PART_01               USABLE
TEST_PART_IDX         PART_02               USABLE
TEST_PART_IDX         PART_03               USABLE
TEST_PART_IDX         PART_04               USABLE

4 rows selected.

Partition Exchange 수행


  • ALTER TABLE 구문으로 Partition Exchange를 수행하다.
  • 대상 PartitionPART_02이다.
SQL> ALTER TABLE TEST_PART EXCHANGE PARTITION PART_02 WITH TABLE TEST_NON ;

Table 'TEST_PART' altered.
  • 생성된 Index key column에 차이가 있는 경우 TBR-7280: Index key columns do not match. 에러가 발생한다.
$ tberr 7280
/*
 * err:   -7280
 * name:  ERROR_DDL_DIFFERENT_INDEX_COLUMN
 * desc:   Index key columns do not match.   
 * cause:  Index key columns in the tables do not match.   
 * action: Unable to execute this command.;
 */
  • 변경된 SEGMENT를 정보 조회하면 Tablespace가 변경된 것을 확인할 수 있다.
  • PART_02TEST_NONTablespace가 바뀌었다.
    (Index도 마찬가지)
SQL> -- SEGMENT별 Tablespace 정보
SQL> SELECT SEGMENT_NAME, PARTITION_NAME, TABLESPACE_NAME
       FROM USER_SEGMENTS
      ORDER BY 1, 2
     ;

SEGMENT_NAME         PARTITION_NAME        TABLESPACE_NAME     
-------------------- --------------------- --------------------
TEST_NON                                   USR
TEST_NON_IDX                               USR
TEST_PART            PART_01               USR
TEST_PART            PART_02               USR2
TEST_PART            PART_03               USR
TEST_PART            PART_04               USR
TEST_PART_IDX        PART_01               USR
TEST_PART_IDX        PART_02               USR2
TEST_PART_IDX        PART_03               USR
TEST_PART_IDX        PART_04               USR

10 rows selected.
  • Index의 상태를 조회하면 UNUSABLE인 것을 알 수 있다.
  • Index Partition의 경우 교체된 PART_02UNUSABLE 상태가 된다.
  • 단, Local Partitioned Index인 경우만 그렇고 Global Partitioned Index의 경우 모든 Index PartitionUNUSABLE 상태가 된다.
SQL> -- Index 상태 조회
SQL> SELECT INDEX_NAME, STATUS
       FROM USER_INDEXES
      ORDER BY 1
     ;

INDEX_NAME            STATUS  
--------------------- --------
TEST_NON_IDX          UNUSABLE
TEST_PART_IDX         UNUSABLE

2 rows selected.

SQL> -- Index Partition 상태 조회
SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
       FROM USER_IND_PARTITIONS
      ORDER BY 1, 2
     ;

INDEX_NAME            PARTITION_NAME        STATUS  
--------------------- --------------------- --------
TEST_PART_IDX         PART_01               USABLE
TEST_PART_IDX         PART_02               UNUSABLE
TEST_PART_IDX         PART_03               USABLE
TEST_PART_IDX         PART_04               USABLE

4 rows selected.

Partition Exchange 후처리


  • 미리 언급했듯이 Index가 문제가 된다.
  • UNUSABLE 상태이므로 REBUILD가 필요하다.
  • INDEX REBUILD의 경우 필요한 Index에만 수행하면 된다.
  • 사실 특정 파티션의 인덱스를 재생성할 수 있는 기능2도 신규기능이다.
    (하지만 이것도 전에 되던 거다.)
  • Global Partitioned Index의 경우 Index 전체 REBUILD가 필요하다.
SQL> -- Index Partition의 REBUILD 수행
SQL> ALTER INDEX TEST_PART_IDX REBUILD PARTITION PART_02 ;

Index 'TEST_PART_IDX' altered.

SQL> -- Index의 REBUILD 수행
SQL> ALTER INDEX TEST_NON_IDX REBUILD ;

Index 'TEST_NON_IDX' altered.
  • Index 상태를 조회하면 VALID 또는 USABLE인 것을 알수 있다.
SQL> -- Index 상태 조회
SQL> SELECT INDEX_NAME, STATUS
       FROM USER_INDEXES
      ORDER BY 1
     ;

INDEX_NAME            STATUS  
--------------------- --------
TEST_NON_IDX          VALID
TEST_PART_IDX         VALID

2 rows selected.

SQL> -- Index Partition 상태 조회
SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
       FROM USER_IND_PARTITIONS
      ORDER BY 1, 2
     ;

INDEX_NAME            PARTITION_NAME        STATUS  
--------------------- --------------------- --------
TEST_PART_IDX         PART_01               USABLE
TEST_PART_IDX         PART_02               USABLE
TEST_PART_IDX         PART_03               USABLE
TEST_PART_IDX         PART_04               USABLE

4 rows selected.

Partition Key 위배 시


  • 해당 파트는 TablePartition Key를 위배하는 데이터가 있는 경우
    WITHOUT VALIDATION 옵션을 통해 교체 가능 한지에 대한 테스트다.
  • 하지만, 실제 대용량의 Table을 교체하는 경우 해당 옵션을 사용하면 검증단계를 생략하므로 좀 더 효율적일 수 있다.

  • TEST_NON의 A 컬럼에는 ‘1’만 들어있다. (기존 Partition key가 ‘1’이었다)

  • 테스트를 위해 Table에 ‘1’이 넘는 데이터를 넣어보자.
SQL> INSERT INTO TEST_NON
     SELECT CEIL(DBMS_RANDOM.VALUE(1,10)) A,
            LEVEL B,
            DBMS_RANDOM.STRING('X',100) C,
            TO_DATE(SYSDATE + LEVEL/24/60/60) D
       FROM DUAL
     CONNECT BY LEVEL <= 1000
     ;

1000 rows inserted.

SQL> COMMIT ;

Commit completed.`
  • 데이터가 추가된 상태에서 Partition Exchange 시도하면 아래와 같은 에러가 발생한다.
SQL> ALTER TABLE TEST_PART EXCHANGE PARTITION PART_02 WITH TABLE TEST_NON ;
TBR-7287: Some rows in the table are invalid for the specified partition.
  • 에러 내용은 아래와 같다.
tberr -7287
/*
 * err:   -7287
 * name:  ERROR_DDL_ROWS_DONT_QUALIFY_FOR_PARTITION
 * desc:   Some rows in the table are invalid for the specified partition.
 * cause:  Some rows cannot be inserted in the specified partition.
 * action: Remove the invalid rows and try again.;
 */
  • 해당 상황이 비정상적인 경우 해당 데이터를 삭제해야 한다.
  • 하지만, 정상적이라고 판단되는 경우 강제로라도 교체가 이루어져야 한다.
  • 따라서, WITHOUT VALIDATION 옵션으로 Partition Exchange 수행한다고 해보자.
SQL> ALTER TABLE TEST_PART EXCHANGE PARTITION PART_02 WITH TABLE TEST_NON WITHOUT VALIDATION ;

Table 'TEST_PART' altered.
  • 변경된 SEGMENT를 정보 조회하면 Tablespace가 변경된 것을 확인할 수 있다.
SQL> -- SEGMENT별 Tablespace 정보
SQL> SELECT SEGMENT_NAME, PARTITION_NAME, TABLESPACE_NAME
       FROM USER_SEGMENTS
      ORDER BY 1, 2
     ;

SEGMENT_NAME         PARTITION_NAME        TABLESPACE_NAME     
-------------------- --------------------- --------------------
TEST_NON                                   USR2
TEST_NON_IDX                               USR2
TEST_PART            PART_01               USR
TEST_PART            PART_02               USR
TEST_PART            PART_03               USR
TEST_PART            PART_04               USR
TEST_PART_IDX        PART_01               USR
TEST_PART_IDX        PART_02               USR
TEST_PART_IDX        PART_03               USR
TEST_PART_IDX        PART_04               USR

10 rows selected.
  • Index의 상태 역시 UNUSABLE인 것을 알 수 있다.
SQL> -- Index 상태 조회
SQL> SELECT INDEX_NAME, STATUS
       FROM USER_INDEXES
      ORDER BY 1
     ;

INDEX_NAME            STATUS  
--------------------- --------
TEST_NON_IDX          UNUSABLE
TEST_PART_IDX         UNUSABLE

2 rows selected.

SQL> -- Index Partition 상태 조회
SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
       FROM USER_IND_PARTITIONS
      ORDER BY 1, 2
     ;

INDEX_NAME            PARTITION_NAME        STATUS  
--------------------- --------------------- --------
TEST_PART_IDX         PART_01               USABLE
TEST_PART_IDX         PART_02               UNUSABLE
TEST_PART_IDX         PART_03               USABLE
TEST_PART_IDX         PART_04               USABLE

4 rows selected.
  • 기존과 동일하게 후처리(REBUILD)를 해준다.
SQL> -- Index Partition의 REBUILD 수행
SQL> ALTER INDEX TEST_PART_IDX REBUILD PARTITION PART_02 ;

Index 'TEST_PART_IDX' altered.

SQL> -- Index의 REBUILD 수행
SQL> ALTER INDEX TEST_NON_IDX REBUILD ;

Index 'TEST_NON_IDX' altered.
  • 실제 교체된 Partition(PART_02)의 데이터를 조회하면
    Partition key에 위배되는 데이터가 존재하는 것을 알 수 있다.
SELECT COUNT(*) FROM TEST_PART PARTITION(PART_02)
 WHERE A <> 1
;

  COUNT(*)
----------
      1000

1 row selected.

여담


이전 테스트 때문에 Tibero6 FS05 최신 패치를 먹였다. (본 테스트와는 상관없다)
Tibero 4 이후 추가된 것으로 보인다. (4 SP1인진 정확하지 않다)
Tibero 6에서보다 오히려 Tibero 5에서는 파라미터를 먹이면 더 유용하게 쓸 수 있다.
(파라미터가 Hidden이라 문제지)
본의 아니게 두 가지 기능을 테스트했다.

'Tibero > Tibero6' 카테고리의 다른 글

신규 기능 - Recursive With  (0) 2017.05.29
신규 기능 - 원격 저장소를 가진 실체화 뷰  (0) 2017.05.22
신규기능 - BINARY TIP  (0) 2017.01.03
신규 기능 - Listener Multi-port  (0) 2016.11.10
신규 기능 - OFFLINE FOR DROP  (0) 2016.11.03

댓글