变更表类型及分区策略

PolarDB-X支持变更表的类型(即在单表、广播表和分区表三者间进行相互转换),和变更分区表的分区策略(包括分区函数或分区列)。本文介绍相关语法和示例。

前提条件

  • 仅适用于分区模式为 auto 的逻辑库(请参见CREATE DATABASE

  • 仅内核小版本为 5.4.13 或以上的 PolarDB-X 2.0 实例支持变更表的类型,和变更表的分区策略。

  • 仅内核小版本为 5.4.13 或以上的 PolarDB-X 2.0 实例支持对带有GSI的分区表进行分区变更。

  • 仅内核小版本为 5.4.14 或以上的 PolarDB-X 2.0 实例支持将普通分区表转为默认主键分区表。

  • 仅内核小版本为 5.4.14 或以上的 PolarDB-X 2.0 实例支持修改默认主键拆分表的分区数。

如何查看实例版本

您可以先连接PolarDB-X 2.0数据库,再通过执行如下 select version() 命令查看目标实例的当前版本:

mysql> select version();
+-----------------------------+
| VERSION()                   |
+-----------------------------+
| 5.6.29-TDDL-5.4.8-16079964  |
+-----------------------------+
1 row in set (0.00 sec)

注意事项

  • 表属性变更后,主键分区表将变成普通表(即不再适用原主键分区表中的自动分区策略或索引转换规则)。更多详情,请参见主键拆分
  • 本文中关于变更分区表、广播表和单表的表类型示例,均在单表t_order的基础上进行变更,t_order表的创建语句如下:

    CREATE TABLE t_order (
      `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子句创建的表,系统会将该表复制到每个分库上,并通过分布式事务实现数据一致性。更多详情,请参见单表与广播表

单表或广播表变为分区表

  • 语法

    ALTER TABLE table_name partition_options;
    
  • 说明

    更多关于partition_options的信息,请参见CREATE TABLE

  • 示例

    因业务扩展,单表t_order无法承载日益增长的数据。此时,您可以使用如下语句将该单表变更为分区表(以order_id为分区键,采用KEY分区策略):

    ALTER TABLE t_order PARTITION BY KEY(`order_id`);
    

    如需指定分区数量,可以使用如下语句:

    ALTER TABLE t_order PARTITION BY KEY(`order_id`) PARTITIONS 8;
    

单表或分区表变为广播表

  • 语法

    ALTER TABLE table_name BROADCAST;
    
  • 示例

    您可以使用如下语句将单表或拆分表t_order变更为广播表:

    ALTER TABLE t_order BROADCAST;
    

广播表或分区表变为单表

  • 语法

    ALTER TABLE table_name SINGLE;
    
  • 示例

    您可以使用如下语句将广播表或拆分表t_order变更为单表:

    ALTER TABLE t_order SINGLE;
    

变更分区表的分区策略

  • 语法

    ALTER TABLE tbl_name drds_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
    

相关文档

分区策略变更后,您可以通过如下命令查看表的分区策略或拓扑结构:

常见问题

Q:为什么有时拆分键变更的DDL任务会执行失败?此时该如何处理?

A:实例崩溃或唯一索引存在冲突等因素会导致拆分规则变更的DDL任务执行失败。但这不会损坏原表任何数据,也不会阻塞正常的DML和查询语句执行。当拆分键变更的DDL任务执行失败时,您可以通过ROLLBACK DDL命令回滚该任务,然后再次尝试变更。关于ROLLBACK DDL命令的详情,请参见回滚任务

results matching ""

    No results matching ""