MySQL Partition 파티션(3) - Partition Exchange

Share

Last Updated on 1월 20, 2024 by Jade(정현호)

안녕하세요  
이번에는 MySQL 의 Partition Exchange 에 대 한 내용을 확인해보도록 하겠습니다.    

해당 포스팅은 아래 이전 포스팅에서 이어지는 글입니다. 
 • MySQL Partition (1) - 정의와 기능 설명 파티션 제약사항
 • MySQL Partition (2) - 파티션 종류 와 파티션 테이블 생성 과 변경
            

사전 테이블 준비

Partition Exchange 는 MySQL 5.6 버전부터 지원되는 기능입니다.

특정 파티션에 대한 삭제 시 락(잠금)이나 부하에 대한 최소화 및 일반 테이블을 특정 파티션으로 하고자 할 때 작업 영향도를 최소화하면서 파티션 작업을 수행할 수 있습니다.


테스트 테이블 생성
기능 확인 및 테스트를 위해서 테스트 테이블 생성 및 데이터를 입력하도록 하겠습니다.

-- 테이블 생성
mysql> CREATE TABLE `tb_range_table`
(id int not null,
name varchar(10),
dept varchar(10),
hiredate date not null default '2010-01-01'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
Partition by range(YEAR(hiredate)) (
partition p0 VALUES LESS THAN(2011) ENGINE=InnoDB,
partition p1 VALUES LESS THAN(2012) ENGINE=InnoDB,
partition p2 VALUES LESS THAN(2013) ENGINE=InnoDB,
partition p3 VALUES LESS THAN(2014) ENGINE=InnoDB,
partition p999 VALUES LESS THAN MAXVALUE ENGINE=InnoDB
);

-- 데이터 입력
mysql> insert into `tb_range_table` values(1,'A','A','2013-02-05'),
(2,'A','A','2013-03-05'),(3,'A','A','2013-04-05'),
(4,'A','A','2013-05-05'),(5,'A','A','2013-06-05');



파티션 정보 조회
위에서 생성된 파티션 정보를 확인해 보도록 하겠습니다.

mysql> SELECT TABLE_SCHEMA, TABLE_NAME, 
PARTITION_NAME as PART_NAME, 
PARTITION_ORDINAL_POSITION as PART_POS, 
TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME = 'tb_range_table';

+--------------+----------------+-----------+----------+------------+
| TABLE_SCHEMA | TABLE_NAME     | PART_NAME | PART_POS | TABLE_ROWS |
+--------------+----------------+-----------+----------+------------+
| test         | tb_range_table | p0        |        1 |          0 |
| test         | tb_range_table | p1        |        2 |          0 |
| test         | tb_range_table | p2        |        3 |          0 |
| test         | tb_range_table | p3        |        4 |          5 | <-- 5건 확인됨
| test         | tb_range_table | p999      |        5 |          0 |
+--------------+----------------+-----------+----------+------------+



동일 구조의 일반 테이블을 생성
Exchange Partition 테스트를 위한 테이블 생성 동일 구조의 일반 테이블을 생성합니다.

mysql> create table `tb_single_table` like `tb_range_table`;



모든 파티션 삭제
이전 단계에서 create table like  명령어를 통해서 동일한 구조의 테이블을 생성하였습니다.
파티션 구조도 동일하게 생성 되어있기 때문에 Partition exchange 을 모든 파티션을 삭제하도록 하겠습니다.

mysql> alter table `tb_single_table` remove partitioning;


[참고1] Partition exchange 시 대상 테이블
exchange 할 테이블과 원본 테이블은 구조가 동일해야 하며, exchange 할 테이블이 이미 파티션이 되어있을 경우 다음과 같은 에러가 발생합니다.
ERROR 1732 (HY000): Table to exchange with partition is partitioned: 테이블명

[참고2] remove partitioning과 drop partition의 차이점은 일단 drop은 파티션을 삭제하면서 파티션에 포함한 데이터도 삭제되지만
 remove 은 파티션은 삭제하지만 데이터는 남게 됩니다.

remove partitioning는 테이블의 전체 파티션을 없애고 drop 은 특정 파티션만 드랍(삭제) 하게 됩니다.


테스트 테이블 건수 확인

mysql> select count(*) 
from tb_single_table;

+----------+
| count(*) |
+----------+
|     0    |
+----------+


mysql> select count(*) 
from tb_range_table;

+----------+
| count(*) |
+----------+
|     5    |  <-- 5건
+----------+

                 

Partition exchange

이전 단계에서 생성한 테스트 테이블을 통해서  Partition exchange 를 진행하도록 하겠습니다.


파티션 exchange 수행
파티션 테이블 과 일반 테이블을 통해서 Partition exchange 를 진행하도록 하겠습니다.

mysql> alter table `tb_range_table`
algorithm=inplace, lock=none,
exchange partition p3 
with table `tb_single_table`;

Partition exchange 작업도 "algorithm=inplace, lock=none" 옵션 사용이 가능 합니다.


일반 테이블 건수 확인

mysql> select count(*) 
from tb_range_table;
+----------+
| count(*) |
+----------+
|    0     |  <--5건에서 0건으로 변경됨
+----------+
 

mysql> select count(*) 
from tb_single_table;
+----------+
| count(*) |
+----------+
|    5     |  <-- 일반 테이블이 0건에서 5건이 됨
+----------+



파티션 정보 조회

mysql> SELECT TABLE_SCHEMA, TABLE_NAME, 
PARTITION_NAME, PARTITION_ORDINAL_POSITION, 
TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME = 'tb_range_table';
+------------+----------------+-----------+----------+----------+
| TAB_SCHEMA | TABLE_NAME     | PART_NAME | PART_POS | TAB_ROWS |
+------------+----------------+-----------+----------+----------+
|   test     | tb_range_table |    p0     |     1    |     0    |
|   test     | tb_range_table |    p1     |     2    |     0    |
|   test     | tb_range_table |    p2     |     3    |     0    |
|   test     | tb_range_table |    p3     |     4    |     0    | <-- 5건에서 0으로 변경됨
|   test     | tb_range_table |   p999    |     5    |     0    |
+------------+----------------+-----------+----------+----------+



파티션 및 임시 테이블 제거
원본 테이블의 파티션 제거 및 임시 테이블 제거합니다.

mysql> alter table `tb_range_table` drop partition p3;
mysql> drop table `tb_single_table`;



파티션 테이블로 변경
추가적인 내용으로 Partition exchange 를 통해서 일반 테이블로 변경된(P3 파티션 -> 일반 테이블) 이 후, alter 명령어를 통해서 다시 파티션으로 변경할 수는 있습니다.


일반 테이블에서 파티션으로 변경 명령어 예시

mysql> alter table `tb_single_table`
PARTITION BY RANGE(YEAR(hiredate))
(
partition p0 VALUES LESS THAN(2011) ENGINE=InnoDB,
partition p1 VALUES LESS THAN(2012) ENGINE=InnoDB,
partition p2 VALUES LESS THAN(2013) ENGINE=InnoDB,
partition p3 VALUES LESS THAN(2014) ENGINE=InnoDB
);



다른 파티션 테이블로의 Exchange
Partition Exchange
를 통해서 일반 테이블로 변경된(P3 파티션 -> 일반 테이블) 데이터를 테이블 구조가 같은 다른 파티션 테이블로 다시 Partition Exchange 할 수 있습니다.


이 경우는 파티션 테이블에서 -> 다른 파티션 테이블로 파티션 이동(Exchange) 를 위해서 사용하는 경우가 될 수 있습니다.

위에서 tb_range_table 테이블의 p3 파티션과 tb_single_table 테이블을 exchange 하였습니다. 그 상황에서 아래와 같이 구조가 같은 다른 테이블을 생성하도록 하겠습니다.

새로운 파티션 테이블 생성

mysql> CREATE TABLE `tb_range_table_history`
(id int not null,
name varchar(10),
dept varchar(10),
hiredate date not null default '2010-01-01'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
Partition by range(YEAR(hiredate)) (
partition p0 VALUES LESS THAN(2011) ENGINE=InnoDB,
partition p1 VALUES LESS THAN(2012) ENGINE=InnoDB,
partition p2 VALUES LESS THAN(2013) ENGINE=InnoDB,
partition p3 VALUES LESS THAN(2014) ENGINE=InnoDB,
partition p999 VALUES LESS THAN MAXVALUE ENGINE=InnoDB
);


Partition Exchange 실행
tb_single_table 테이블과 tb_range_table_history의 p3 파티션을 Exchange를 수행합니다.

mysql> alter table `tb_range_table_history`
algorithm=inplace, lock=none,
exchange partition p3 
with table `tb_single_table`;


Partition Exchange 실행

-- 일반 테이블
mysql> select count(*) from tb_single_table;
+----------+
| count(*) |
+----------+
|        0 |
+----------+

-- 파티션 테이블
mysql> select count(*) from tb_range_table_history;
+----------+
| count(*) |
+----------+
|        5 |
+----------+


이와 같이 파티션 테이블 -> 일반 테이블 -> 다른 파티션 테이블 순으로 파티션 데이터에 대한 이동으로 사용할 수도 있습니다.


ROW_FORMAT 관련
partition exchange 시 파티션 테이블과 비 파티션 테이블의 ROW_FORMAT 속성이 동일 해야 합니다.
예를들어 한쪽 테이블의 COMPRESS(압축) 기능을 사용하여 ROW_FORMAT이 테이블 간에 서로 다를 경우 2개 테이블 모두 COMPRESS(압축)을 설정하거나 둘다 압축을 사용하지 않거나 와 같이 두개 테이블 간에 같은 ROW_FORMAT 속성을 가지고 있어야 합니다.

다를 경우 partition exchange시 다음과 같은 에러가 발생합니다.

ERROR 1731 (HY000): Non Matching attribute 'ROW_FORMAT' between partition and table


MySQL 압축(COMPRESS) 기능은 다음 포스팅을 참조하시면 됩니다.

             

Summary

MySQL은 파티션 테이블에 대한 다양한 기능을 제공하고 있으며, 다른 RDBMS에서 제공하는 대부분의 파티션 기능을 제공하고 있습니다. 

많은 데이터가 존재하는 테이블이 파티션으로 구성 되어있을 경우 drop partition 또는 truncate partition 을 하기 전에 먼저 Partition exchange 를 하게 되면 많은 데이터가 있는 테이블의 drop/truncate 작업에 대해서 부하를 줄이면서 빠르게 진행할 수 있습니다.
(Partition exchange 작업도 Online DDL 이 지원됩니다.)

MySQL 8.0에서 exchange partitions 기능과 관련된 파티션 제약사항이 추가되었으며, 파티션된 테이블에 컬럼 추가시 Online DDL의 ALGORITHM=INSTANT 옵션을 사용하면 더 이상 해당 테이블은 exchange partitions 이 불가합니다. 


용량이 많고 사용량이 많은 테이블이라면 Partition exchange 를 먼저 진행 후에 exchange 된 일반 테이블을 정리하는 프로세스로 작업하시는 것을 고려 해보시기 바랍니다.
             

Reference

Reference URL
dev.mysql.com/5.6/partitioning-management-exchange


연관된 글

 



0
글에 대한 당신의 생각을 기다립니다. 댓글 의견 주세요!x