本文介绍了变更表类型(即在单表、广播表和分区表三者间进行相互转换)及分区策略(包括拆分函数或分区列)的相关语法和示例。本语法仅适用于AUTO模式数据库。
前提条件
- 仅适用于分区模式为auto/partitioning的逻辑库(请参见CREATE DATABASE);
- 仅内核小版本为5.4.13或以上的PolarDB-X实例支持变更表的类型和分区策略。
- 仅内核小版本为5.4.13或以上的PolarDB-X实例支持对带有GSI的分区表进行分区变更。
- 仅内核小版本为5.4.14或以上的PolarDB-X实例支持将普通分区表转为默认主键分区表。
- 仅内核小版本为5.4.14或以上的PolarDB-X实例支持修改默认主键分区表的分区数。
如何查看实例版本,请参见查看实例版本。
注意事项
- 表属性变更后,主键分区表将变成普通表(即不再适用原主键分区表中的自动分区策略或索引转换规则)。更多详情,请参见AUTO模式下的主键拆分。
- 本文中关于变更分区表、广播表和单表的表类型示例,均在单表
t_order1
的基础上进行变更,t_order1
表的创建语句如下:CREATE TABLE t_order1 ( `id` bigint(11) NOT NULL AUTO_INCREMENT BY GROUP, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext DEFAULT NULL, `order_detail` longtext DEFAULT NULL, PRIMARY KEY (`id`), KEY `l_i_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
表类型
PolarDB-X实例支持3种类型的表:分区表、广播表和单表。您可以通过ALTER TABLE语句将表的类型在分区表、广播表和单表之间进行转换,同时还能对分区表的分区策略进行变更。
- 分区表
使用
partition_options
分区子句进行创建的表。partition_options
可以是如下子句:partition_options: PARTITION BY HASH({column_name | partition_func(column_name)}) | KEY(column_list) | RANGE{({column_name | partition_func(column_name)}) | RANGE COLUMNS(column_list)} | LIST{({column_name | partition_func(column_name)}) | LIST COLUMNS(column_list)} } partition_list_spec
说明 更多关于分区策略的信息,请参见 分区类型介绍。 - 广播表
通过
BROADCAST
子句创建的表,系统会将该表复制到每个分库上,并通过分布式事务实现数据一致性。更多详情,请参见单表与广播表。 - 单表
通过
SINGLE
子句创建的表。更多详情,请参见单表与广播表。
单表或广播表变为分区表
- 语法
ALTER TABLE table_name partition_options;
说明更多关于
partition_options
的信息,请参见CREATE TABLE(AUTO模式)。 - 示例
因业务扩展,单表
t_order1
无法承载日益增长的数据。此时,您可以使用如下语句将该单表变更为分区表(以order_id
为分区键,采用KEY分区策略):ALTER TABLE t_order1 PARTITION BY KEY(`order_id`);
如需指定分区数量,可以使用如下语句:ALTER TABLE t_order1 PARTITION BY KEY(`order_id`) PARTITIONS 8;
单表或分区表变为广播表
- 语法
ALTER TABLE table_name BROADCAST;
- 示例
您可以使用如下语句将单表或分区表
t_order1
变更为广播表:ALTER TABLE t_order1 BROADCAST;
广播表或分区表变为单表
- 语法
ALTER TABLE table_name SINGLE;
- 示例
您可以使用如下语句将广播表或分区表
t_order1
变更为单表:ALTER TABLE t_order1 SINGLE;
变更分区表的分区策略
- 语法
ALTER TABLE tbl_name partition_options;
- 示例1
假设已使用如下语句在 PolarDB-X数据库中创建了一张分区表
t_order
(根据order_id
列进行KEY分区):CREATE TABLE t_order ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext DEFAULT NULL, `order_detail` longtext DEFAULT NULL, PRIMARY KEY (`id`), KEY `l_i_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 PARTITION BY KEY(`order_id`);
现需要对t_order
表的分区策略作出如下变更:- 根据
order_id
列以及buyer_id
进行KEY分区。 - 共包含8个分区。
您可以使用如下语句实现上述变更:
ALTER TABLE t_order PARTITION BY KEY(order_id, buyer_id) PARTITIONS 8;
变更后执行show create table t_order
,返回如下信息:CREATE TABLE `t_order` ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext, `order_detail` longtext, PRIMARY KEY (`id`), KEY `l_i_order` (`order_id`), KEY `auto_shard_key_order_id_buyer_id` USING BTREE (`order_id`, `buyer_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`order_id`,`buyer_id`) PARTITIONS 8
- 根据
- 示例2
假设已使用如下语句在 PolarDB-X数据库中创建了一张分区表
t_order
(根据id
列进行RANGE分区):CREATE TABLE t_order ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext DEFAULT NULL, `order_detail` longtext DEFAULT NULL, PRIMARY KEY (`id`), KEY `l_i_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 PARTITION BY RANGE(`id`) ( PARTITION p1 VALUES LESS THAN (100), PARTITION p2 VALUES LESS THAN (1000), PARTITION P3 VALUES LESS THAN MAXVALUE );
现需要对t_order
表的分区策略作出如下变更:- 根据
order_id
列以及buyer_id
进行KEY分区; - 总共包含16个分区。
您可以使用如下语句实现上述变更:
变更后执行ALTER TABLE t_order PARTITION BY KEY(order_id, buyer_id) PARTITIONS 16;
show create table t_order
,返回如下信息:CREATE TABLE `t_order` ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext, `order_detail` longtext, PRIMARY KEY (`id`), KEY `l_i_order` (`order_id`), KEY `auto_shard_key_order_id_buyer_id` USING BTREE (`order_id`, `buyer_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`order_id`,`buyer_id`) PARTITIONS 16
- 根据
分区表变为默认主键分区表
- 语法
ALTER TABLE table_name REMOVE PARTITIONING;
- 示例
假设已使用如下语句在PolarDB-X数据库中创建了一张分区表
t_order
(根据order_id
列进行KEY分区):CREATE TABLE t_order ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext DEFAULT NULL, `order_detail` longtext DEFAULT NULL, PRIMARY KEY (`id`), KEY `l_i_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 PARTITION BY KEY(`order_id`);
现需要对
t_order
表的分区策略作出如下变更:- 将其改成按照主键列
id
进行KEY分区; show create table t_order
不再对外展示分区信息。
您可以使用如下语句实现上述变更:
ALTER TABLE t_order REMOVE PARTITIONING;
变更后执行
show create table t_order
,返回如下信息:CREATE TABLE t_order ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext DEFAULT NULL, `order_detail` longtext DEFAULT NULL, PRIMARY KEY (`id`), KEY `l_i_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
重要- 该转换会保留原表已经存在的GLOBAL INDEX,而LOCAL INDEX会变为GLOBAL INDEX。
- 单表或者广播表不可直接转成默认主键拆分表。
- 将其改成按照主键列
变更默认主键分区表的分区数
- 语法
ALTER TABLE table_name PARTITIONS partition_count;
说明 仅默认主键拆分表可以使用该指令一键改变分区数,且转换后依然是默认主键分区表。 - 示例
假设已使用如下语句在PolarDB-X数据库中创建了一张分区表
t_order
(默认根据id
列进行KEY分区):CREATE TABLE t_order ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext DEFAULT NULL, `order_detail` longtext DEFAULT NULL, PRIMARY KEY (`id`), KEY `l_i_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
执行
show full create table t_order
可以看到该表具体的分区方式以及分区数:CREATE PARTITION TABLE `t_order` ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext, `order_detail` longtext, PRIMARY KEY (`id`), GLOBAL INDEX /* l_i_order_$d8df */ `l_i_order` (`order_id`) PARTITION BY KEY (`order_id`, `id`) PARTITIONS 16, LOCAL KEY `_local_l_i_order` (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 16
现需要对
t_order
表的分区策略作出如下变更:- 将分区数从16改为32。
- 不会将改默认主键分区表转为普通分区表。
- 同时修改原表上的 GLOBAL INDEX 的分区数。
您可以使用如下语句实现上述变更:
ALTER TABLE t_order PARTITIONS 32;
变更后执行
show full create table t_order
,返回如下信息:CREATE PARTITION TABLE `t_order` ( `id` bigint(11) NOT NULL, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext, `order_detail` longtext, PRIMARY KEY USING BTREE (`id`), GLOBAL INDEX /* l_i_order_$d8df */ `l_i_order` (`order_id`) PARTITION BY KEY (`order_id`, `id`) PARTITIONS 32, LOCAL KEY `_local_l_i_order` (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8 PARTITION BY KEY(`id`) PARTITIONS 32
相关文档
- 查看表分区规则,请使用
SHOW CREATE TABLE tablename
。 - 查看表拓扑结构,请参见SHOW TOPOLOGY FROM tablename。
常见问题
Q:为什么有时分区变更的DDL任务会执行失败?此时该如何处理?
A:实例崩溃或唯一索引存在冲突等因素会导致分区变更的DDL任务执行失败。但这不会损坏原表任何数据,也不会阻塞正常的DML和查询语句执行。当分区变更的DDL任务执行失败时,您可以通过CANCEL DDL
命令回滚该任务,然后再次尝试变更。关于CANCEL DDL
命令的详情,请参见CANCEL DDL。