从 RANGE 或者 LIST 分区的表中删除一个分区,可以使用 ALTER TABLE DROP PARTITION 来实现。
alter table emp_range_man drop partition p2;
删除 LIST 分区和删除 RANGE 分区使用的语句完全相同,但是删除 LIST 分区后,由于在 LIST 分区定义中不再包含已经被删除了的分区的值列表,所以后续无法写入包含有已经删除了的分区的值列表的数据。
#创建 RANGE 分区表
mysql> create table emp_range_man(
-> a int
-> )partition by range(a)(
-> partition p0 values less than(5),
-> partition p1 values less than(10),
-> partition p2 values less than(15),
-> partition p3 values less than(maxvalue)
-> );
Query OK, 0 rows affected (0.33 sec)
#插入数据
mysql> insert into emp_range_man values(1),(2),(6),(7),(11),(12),(16),(17);
Query OK, 8 rows affected (0.01 sec)
#查看数据分布
mysql> select partition_name,partition_expression,partition_description,table_rows from information_schema.partitions where table_schema=schema() and table_name='emp_range_man';
+----------------+----------------------+-----------------------+------------+
| partition_name | partition_expression | partition_description | table_rows |
+----------------+----------------------+-----------------------+------------+
| p0 | a | 5 | 2 |
| p1 | a | 10 | 2 |
| p2 | a | 15 | 2 |
| p3 | a | MAXVALUE | 2 |
+----------------+----------------------+-----------------------+------------+
4 rows in set (0.00 sec)
#查看表数据
mysql> select * from emp_range_man;
+------+
| a |
+------+
| 1 |
| 2 |
| 6 |
| 7 |
| 11 |
| 12 |
| 16 |
| 17 |
+------+
8 rows in set (0.00 sec)
#删除表分区
mysql> alter table emp_range_man drop partition p2;
Query OK, 0 rows affected (0.03 sec)
#查看表结构
mysql> show create table emp_range_man \G;
*************************** 1. row ***************************
Table: emp_range_man
Create Table: CREATE TABLE `emp_range_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (a)
(PARTITION p0 VALUES LESS THAN (5) ENGINE = InnoDB,
PARTITION p1 VALUES LESS THAN (10) ENGINE = InnoDB,
PARTITION p3 VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
1 row in set (0.00 sec)
#查看表数据
mysql> select * from emp_range_man;
+------+
| a |
+------+
| 1 |
| 2 |
| 6 |
| 7 |
| 16 |
| 17 |
+------+
6 rows in set (0.00 sec)
#查看数据分布
mysql> select partition_name,partition_expression,partition_description,table_rows from information_schema.partitions where table_schema=schema() and table_name='emp_range_man';
+----------------+----------------------+-----------------------+------------+
| partition_name | partition_expression | partition_description | table_rows |
+----------------+----------------------+-----------------------+------------+
| p0 | a | 5 | 2 |
| p1 | a | 10 | 2 |
| p3 | a | MAXVALUE | 2 |
+----------------+----------------------+-----------------------+------------+
3 rows in set (0.00 sec)
在 RANGE 或者 LIST 分区的表中添加一个分区,可以使用 ALTER TABLE ADD PARTITION 来实现。注意,对于 RANGE 分区只能通过 ADD PARTITION 方式添加新的分区到分区列表的最大一端。
1) RANGE 表分区添加一个新分区
alter table emp_range_man drop partition p3;
#给 RANGE 表分区添加一个新分区
alter table emp_range_man add partition(partition p2 values less than(15));
mysql> show create table emp_range_man \G;
*************************** 1. row ***************************
Table: emp_range_man
Create Table: CREATE TABLE `emp_range_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (a)
(PARTITION p0 VALUES LESS THAN (5) ENGINE = InnoDB,
PARTITION p1 VALUES LESS THAN (10) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (15) ENGINE = InnoDB) */
1 row in set (0.00 sec)
2) LIST 分区添加一个新分区
注意:对于 LIST 分区来说一个固定的分区的分区键值,必须指定并且只能指定一个唯一的分区。也就是说 LIST 分区键值不能重复。
#创建 LIST 分区表
mysql> create table emp_list_man(
-> a int
-> )partition by list(a)(
-> partition p0 values in (1,2),
-> partition p1 values in (5,7,8),
-> partition p2 values in (10,12)
-> );
Query OK, 0 rows affected (0.02 sec)
#给 LIST 分区添加新分区
mysql> alter table emp_list_man add partition(partition p3 values in(9,6));
Query OK, 0 rows affected (0.02 sec)
1) 重新定义 RANGE 分区
注意:重新定义 RANGE 分区时,只能够重新定义相邻的分区,不能跳过某个 RANGE 分区进行重新定义,同时重新定义的分区区间必须和原分区区间覆盖相同的区间。不能使用重新定义分区来改变表分区的类型。
#拆分 RANGE 分区
alter table emp_range_man reorganize partition p3 into(
partition p2 values less than(20),
partition p3 values less than(30)
);
#合并 RANGE 分区
alter table emp_range_man reorganize partition p1,p2,p3 into(
partition p2 values less than(30)
);
#查看当前表结构
mysql> show create table emp_range_man \G;
*************************** 1. row ***************************
Table: emp_range_man
Create Table: CREATE TABLE `emp_range_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (a)
(PARTITION p0 VALUES LESS THAN (5) ENGINE = InnoDB,
PARTITION p1 VALUES LESS THAN (10) ENGINE = InnoDB,
PARTITION p3 VALUES LESS THAN (30) ENGINE = InnoDB,
PARTITION p4 VALUES LESS THAN (50) ENGINE = InnoDB) */
1 row in set (0.00 sec)
#拆分 RANGE 分区
mysql> alter table emp_range_man reorganize partition p3 into(
-> partition p2 values less than(20),
-> partition p3 values less than(30)
-> );
Query OK, 0 rows affected (0.05 sec)
#查看当前表结构
mysql> show create table emp_range_man \G;
*************************** 1. row ***************************
Table: emp_range_man
Create Table: CREATE TABLE `emp_range_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (a)
(PARTITION p0 VALUES LESS THAN (5) ENGINE = InnoDB,
PARTITION p1 VALUES LESS THAN (10) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (20) ENGINE = InnoDB,
PARTITION p3 VALUES LESS THAN (30) ENGINE = InnoDB,
PARTITION p4 VALUES LESS THAN (50) ENGINE = InnoDB) */
1 row in set (0.00 sec)
#合并多个相邻 RANGE 分区为一个 RANGE 分区
mysql> alter table emp_range_man reorganize partition p1,p2,p3 into(
-> partition p2 values less than(30)
-> );
Query OK, 0 rows affected (0.05 sec)
#查看当前表结构
mysql> show create table emp_range_man \G;
*************************** 1. row ***************************
Table: emp_range_man
Create Table: CREATE TABLE `emp_range_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (a)
(PARTITION p0 VALUES LESS THAN (5) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (30) ENGINE = InnoDB,
PARTITION p4 VALUES LESS THAN (50) ENGINE = InnoDB) */
1 row in set (0.00 sec)
2) 重新定义 LIST 分区
注意:重新定义 LIST 分区时,只能够重新定义相邻的分区,不能跳过某个 LIST 分区进行重新定义,同时重新定义的分区区间必须和原分区区间覆盖相同的区间。不能使用重新定义分区来改变表分区的类型。
#合并 LIST 分区
alter table emp_list_man reorganize partition p2,p3,p4 into(
partition p2 values in(10,11,12),
partition p3 values in(9,6)
);
#拆分 LIST 分区
alter table emp_list_man reorganize partition p3 into(
partition p3 values in(9),
partition p4 values in(6)
);
#查看当前表结构
mysql> show create table emp_list_man \G;
*************************** 1. row ***************************
Table: emp_list_man
Create Table: CREATE TABLE `emp_list_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY LIST (a)
(PARTITION p0 VALUES IN (1,2) ENGINE = InnoDB,
PARTITION p1 VALUES IN (5,7,8) ENGINE = InnoDB,
PARTITION p2 VALUES IN (10,12) ENGINE = InnoDB,
PARTITION p3 VALUES IN (9,6) ENGINE = InnoDB,
PARTITION p4 VALUES IN (11) ENGINE = InnoDB) */
1 row in set (0.00 sec)
ERROR:
No query specified
#合并 LIST 分区
mysql> alter table emp_list_man reorganize partition p2,p3,p4 into(
-> partition p2 values in(10,11,12),
-> partition p3 values in(9,6)
-> );
Query OK, 0 rows affected (0.33 sec)
#查看当前表结构
mysql> show create table emp_list_man \G;
*************************** 1. row ***************************
Table: emp_list_man
Create Table: CREATE TABLE `emp_list_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY LIST (a)
(PARTITION p0 VALUES IN (1,2) ENGINE = InnoDB,
PARTITION p1 VALUES IN (5,7,8) ENGINE = InnoDB,
PARTITION p2 VALUES IN (10,11,12) ENGINE = InnoDB,
PARTITION p3 VALUES IN (9,6) ENGINE = InnoDB) */
1 row in set (0.00 sec)
ERROR:
No query specified
#拆分 LIST 分区
mysql> alter table emp_list_man reorganize partition p3 into(
-> partition p3 values in(9),
-> partition p4 values in(6)
-> );
Query OK, 0 rows affected (0.08 sec)
#查看当前表结构
mysql> show create table emp_list_man \G;
*************************** 1. row ***************************
Table: emp_list_man
Create Table: CREATE TABLE `emp_list_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY LIST (a)
(PARTITION p0 VALUES IN (1,2) ENGINE = InnoDB,
PARTITION p1 VALUES IN (5,7,8) ENGINE = InnoDB,
PARTITION p2 VALUES IN (10,11,12) ENGINE = InnoDB,
PARTITION p3 VALUES IN (9) ENGINE = InnoDB,
PARTITION p4 VALUES IN (6) ENGINE = InnoDB) */
1 row in set (0.00 sec)
注意:增加或减少 HASH 和 KEY 分区后,应使用 analyze table tabname 来更新表统计信息以获得准确的表统计信息。
从 HASH 和 KEY 分区的表中删除分区,可以通过 ALTER TABLE TABNAME COALESCE PARTITION NUM 语句来合并 HASH 分区或者 KEY 分区。
#减少表分区
alter table emp_hash_man coalesce partition 2;
#减少表分区后使用 analyze 更新表统计信息
analyze table emp_hash_man;
#创建 HASH 分区表
mysql> create table emp_hash_man(
-> a int
-> )partition by hash(a) partitions 4;
Query OK, 0 rows affected (0.01 sec)
#插入数据
mysql> insert into emp_hash_man values(1),(2),(3),(4),(5),(6),(7),(8);
Query OK, 8 rows affected (0.00 sec)
#查看当前表结构
mysql> show create table emp_hash_man \G;
*************************** 1. row ***************************
Table: emp_hash_man
Create Table: CREATE TABLE `emp_hash_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY HASH (a)
PARTITIONS 4 */
1 row in set (0.00 sec)
ERROR:
No query specified
#查看表数据分布状态
mysql> select partition_name,partition_expression,partition_description,table_rows from information_schema.partitions where table_schema=schema() and table_name='emp_hash_man';
+----------------+----------------------+-----------------------+------------+
| partition_name | partition_expression | partition_description | table_rows |
+----------------+----------------------+-----------------------+------------+
| p0 | a | NULL | 2 |
| p1 | a | NULL | 2 |
| p2 | a | NULL | 2 |
| p3 | a | NULL | 2 |
+----------------+----------------------+-----------------------+------------+
4 rows in set (0.00 sec)
#减少表分区
mysql> alter table emp_hash_man coalesce partition 2;
Query OK, 0 rows affected (0.10 sec)
#查看表数据分布状态
mysql> select partition_name,partition_expression,partition_description,table_rows from information_schema.partitions where table_schema=schema() and table_name='emp_hash_man';
+----------------+----------------------+-----------------------+------------+
| partition_name | partition_expression | partition_description | table_rows |
+----------------+----------------------+-----------------------+------------+
| p0 | a | NULL | 0 |
| p1 | a | NULL | 0 |
+----------------+----------------------+-----------------------+------------+
2 rows in set (0.00 sec)
#使用 analyze 分析表更新表统计信息
mysql> analyze table emp_hash_man;
+-------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+-------------------+---------+----------+----------+
| test.emp_hash_man | analyze | status | OK |
+-------------------+---------+----------+----------+
1 row in set (0.04 sec)
#查看表数据分布状态
mysql> select partition_name,partition_expression,partition_description,table_rows from information_schema.partitions where table_schema=schema() and table_name='emp_hash_man';
+----------------+----------------------+-----------------------+------------+
| partition_name | partition_expression | partition_description | table_rows |
+----------------+----------------------+-----------------------+------------+
| p0 | a | NULL | 4 |
| p1 | a | NULL | 4 |
+----------------+----------------------+-----------------------+------------+
2 rows in set (0.00 sec)
#查看当前表结构
mysql> show create table emp_hash_man \G;
*************************** 1. row ***************************
Table: emp_hash_man
Create Table: CREATE TABLE `emp_hash_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY HASH (a)
PARTITIONS 2 */
1 row in set (0.00 sec)
ERROR:
No query specified
#查看表数据
mysql> select * from emp_hash_man;
+------+
| a |
+------+
| 4 |
| 8 |
| 2 |
| 6 |
| 1 |
| 5 |
| 3 |
| 7 |
+------+
8 rows in set (0.00 sec)
增加 HASH 和 KEY 分区的表中分区数量,可以通过 ALTER TABLE TABNAME ADD PARTITION PARTITIONS NUM 语句来扩张 HASH 分区或者 KEY 分区。
#增加表分区
alter table emp_hash_man add partition partitions 6;
#增加表分区后使用 analyze 更新表统计信息
analyze table emp_hash_man;
#查看当前表结构
mysql> show create table emp_hash_man \G;
*************************** 1. row ***************************
Table: emp_hash_man
Create Table: CREATE TABLE `emp_hash_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY HASH (a)
PARTITIONS 2 */
1 row in set (0.00 sec)
ERROR:
No query specified
#查看当前表数据分布状况
mysql> select partition_name,partition_expression,partition_description,table_rows from information_schema.partitions where table_schema=schema() and table_name='emp_hash_man';
+----------------+----------------------+-----------------------+------------+
| partition_name | partition_expression | partition_description | table_rows |
+----------------+----------------------+-----------------------+------------+
| p0 | a | NULL | 4 |
| p1 | a | NULL | 4 |
+----------------+----------------------+-----------------------+------------+
2 rows in set (0.00 sec)
#新增加 6 个分区
mysql> alter table emp_hash_man add partition partitions 6;
Query OK, 0 rows affected (0.23 sec)
#查看当前表结构
mysql> show create table emp_hash_man \G;
*************************** 1. row ***************************
Table: emp_hash_man
Create Table: CREATE TABLE `emp_hash_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY HASH (a)
PARTITIONS 8 */
1 row in set (0.00 sec)
ERROR:
No query specified
#查看当前表数据分布状况
mysql> select partition_name,partition_expression,partition_description,table_rows from information_schema.partitions where table_schema=schema() and table_name='emp_hash_man';
+----------------+----------------------+-----------------------+------------+
| partition_name | partition_expression | partition_description | table_rows |
+----------------+----------------------+-----------------------+------------+
| p0 | a | NULL | 0 |
| p1 | a | NULL | 0 |
| p2 | a | NULL | 0 |
| p3 | a | NULL | 0 |
| p4 | a | NULL | 0 |
| p5 | a | NULL | 0 |
| p6 | a | NULL | 0 |
| p7 | a | NULL | 0 |
+----------------+----------------------+-----------------------+------------+
8 rows in set (0.00 sec)
#使用 analyze 分析表更新表统计信息
mysql> analyze table emp_hash_man;
+-------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+-------------------+---------+----------+----------+
| test.emp_hash_man | analyze | status | OK |
+-------------------+---------+----------+----------+
1 row in set (0.01 sec)
#查看当前表数据分布状况
mysql> select partition_name,partition_expression,partition_description,table_rows from information_schema.partitions where table_schema=schema() and table_name='emp_hash_man';
+----------------+----------------------+-----------------------+------------+
| partition_name | partition_expression | partition_description | table_rows |
+----------------+----------------------+-----------------------+------------+
| p0 | a | NULL | 1 |
| p1 | a | NULL | 1 |
| p2 | a | NULL | 1 |
| p3 | a | NULL | 1 |
| p4 | a | NULL | 1 |
| p5 | a | NULL | 1 |
| p6 | a | NULL | 1 |
| p7 | a | NULL | 1 |
+----------------+----------------------+-----------------------+------------+
8 rows in set (0.01 sec)
#查看表数据
mysql> select * from emp_hash_man;
+------+
| a |
+------+
| 8 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
+------+
8 rows in set (0.00 sec)
MySQL 5.6 增加了交换分区的功能,可以实现将分区表中的一个分区或者子分区中的数据和普通表中的数据进行交换。
注意:1、普通表不能是临时表。
2、分区表和普通表的结构,除了分区之外,应该完全一致,包括索引的名称和索引列都要一致。
3、普通表不能有外键,也不能有其他表的外键依赖。
4、普通表的所有数据,应该都在分区表分区定义的范围内,在 MySQL 5.7 中,如果确定表中数据都在界限内,可以通过增加 WITHOUT VALIDATION 来跳过这个逐行验证的过程。
5、交换分区不会触发任何被交换的表或分区上的触发器。
6、表中自增列的值会被重置。
7、交换分区的命令中,IGNORE 关键字不会产生影响。
#交换分区命令
alter table emp_hash_man exchange partition p0 with table emp_exchang;
alter table emp_hash_man exchange partition p0 with table emp_exchang WITHOUT VALIDATION;
#将分区表改为非分区表
alter table emp_exchang remove partitioning;
#使用 analyze 分析表更新表统计信息
analyze table emp_hash_man;
#查看 emp_hash_man 表结构
mysql> show create table emp_hash_man \G;
*************************** 1. row ***************************
Table: emp_hash_man
Create Table: CREATE TABLE `emp_hash_man` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY HASH (a)
PARTITIONS 4 */
1 row in set (0.00 sec)
ERROR:
No query specified
#查看表 emp_hash_man 数据分布
mysql> select partition_name,partition_expression,partition_description,table_rows from information_schema.partitions where table_schema=schema() and table_name='emp_hash_man';
+----------------+----------------------+-----------------------+------------+
| partition_name | partition_expression | partition_description | table_rows |
+----------------+----------------------+-----------------------+------------+
| p0 | a | NULL | 2 |
| p1 | a | NULL | 3 |
| p2 | a | NULL | 3 |
| p3 | a | NULL | 2 |
+----------------+----------------------+-----------------------+------------+
4 rows in set (0.00 sec)
#创建一个普通表,表结构和上面的分区表一致
mysql> create table emp_exchang like emp_hash_man;
Query OK, 0 rows affected (0.06 sec)
#查看新建表 emp_exchang 的结构
mysql> show create table emp_exchang \G;
*************************** 1. row ***************************
Table: emp_exchang
Create Table: CREATE TABLE `emp_exchang` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY HASH (a)
PARTITIONS 4 */
1 row in set (0.01 sec)
ERROR:
No query specified
#将分区表改为非分区表
mysql> alter table emp_exchang remove partitioning;
Query OK, 0 rows affected (0.07 sec)
#查看新建表 emp_exchang 的结构
mysql> show create table emp_exchang \G;
*************************** 1. row ***************************
Table: emp_exchang
Create Table: CREATE TABLE `emp_exchang` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
ERROR:
No query specified
#执行交换分区命令
mysql> alter table emp_hash_man exchange partition p0 with table emp_exchang;
Query OK, 0 rows affected (0.01 sec)
#查看表 emp_hash_man 数据分布
mysql> select partition_name,partition_expression,partition_description,table_rows from information_schema.partitions where table_schema=schema() and table_name='emp_hash_man';
+----------------+----------------------+-----------------------+------------+
| partition_name | partition_expression | partition_description | table_rows |
+----------------+----------------------+-----------------------+------------+
| p0 | a | NULL | 0 |
| p1 | a | NULL | 2 |
| p2 | a | NULL | 2 |
| p3 | a | NULL | 2 |
+----------------+----------------------+-----------------------+------------+
4 rows in set (0.00 sec)
#使用 analyze 分析表更新表统计信息
mysql> analyze table emp_hash_man;
+-------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+-------------------+---------+----------+----------+
| test.emp_hash_man | analyze | status | OK |
+-------------------+---------+----------+----------+
1 row in set (0.01 sec)
#查看表 emp_hash_man 数据分布
mysql> select partition_name,partition_expression,partition_description,table_rows from information_schema.partitions where table_schema=schema() and table_name='emp_hash_man';
+----------------+----------------------+-----------------------+------------+
| partition_name | partition_expression | partition_description | table_rows |
+----------------+----------------------+-----------------------+------------+
| p0 | a | NULL | 0 |
| p1 | a | NULL | 3 |
| p2 | a | NULL | 3 |
| p3 | a | NULL | 2 |
+----------------+----------------------+-----------------------+------------+
4 rows in set (0.01 sec)
#查看表 emp_exchang 数据
mysql> select * from emp_exchang;
+------+
| a |
+------+
| 4 |
| 8 |
+------+
2 rows in set (0.00 sec)