本文主要介绍了在AUTO模式数据库下主键拆分表的自动分区规则和索引变换规则。

在自动分区模式的数据库中,如不手动指定分区方式,默认按主键进行拆分。

前提条件

  • PolarDB-X版本为5.4.13及以上。
  • 创建数据库时选择了AUTO模式,即“MODE”选择为“auto/partitioning”,关于创建数据库时的模式选择,请参见CREATE DATABASE

注意事项

  • 除去创建表时指定为单表或广播表,其他表都默认创建为分区表,如不手动指定分区方式,默认按主键进行拆分。
  • 主键拆分表仅支持在建表时指定主键,不支持对已有的表添加或删除主键。如果建表时没有指定主键,则会自动创建隐式主键。
  • 主键拆分表的索引除非第一列不支持自动分区或指定为LOCAL索引,否则自动创建为全局二级索引。
  • 分区策略变更后,主键拆分表将变成普通表(即不再适用原主键拆分表中的自动分区策略或索引转换规则)。如何变更分区策略,请参见变更表类型及分区策略
  • 自动分区数据库中,GSI名称不再要求唯一,建表语句中也不再要求强制指定GSI名称。所有GSI表会携带随机后缀,使用show full create table可以看到这些随机后缀。

语法

自动分区模式下的主键拆分会默认开启,建表语句无需添加特殊关键字,建表语法参见 CREATE TABLE

下面通过几个例子展示分区效果,其中show create table会显示表的精简结构信息,而show full create table会显示完整的表结构。

CREATE TABLE `tb` (
    ->   `x` int NOT NULL AUTO_INCREMENT,
    ->   `y` int NOT NULL,
    ->   `z` float NOT NULL,
    ->   `d` int NOT NULL,
    ->   PRIMARY KEY (x,y,z,d)
    -> );
Query OK, 0 rows affected (0.42 sec)

show create table tb;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| TABLE | CREATE TABLE                                                                                                                                                                                                                                                              |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tb    | CREATE TABLE `tb` (
        `x` int(11) NOT NULL AUTO_INCREMENT,
        `y` int(11) NOT NULL,
        `z` float NOT NULL,
        `d` int(11) NOT NULL,
        PRIMARY KEY (`x`, `y`, `z`, `d`),
        LOCAL KEY `auto_shard_key_x_y_d` USING BTREE (`x`, `y`, `d`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

show full create table tb;
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| TABLE | CREATE TABLE                                                                          |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tb    | CREATE PARTITION TABLE `tb` (
        `x` int(11) NOT NULL AUTO_INCREMENT,
        `y` int(11) NOT NULL,
        `z` float NOT NULL,
        `d` int(11) NOT NULL,
        PRIMARY KEY (`x`, `y`, `z`, `d`),
        LOCAL KEY `auto_shard_key_x_y_d` USING BTREE (`x`, `y`, `d`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`x`,`y`,`d`)
PARTITIONS 16
/* tablegroup = `tg8` */ |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

CREATE TABLE `t_order` (
    -> `x` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> `order_id` varchar(20) DEFAULT NULL,
    -> `seller_id` varchar(20) DEFAULT NULL,
    -> INDEX (`seller_id`),
    -> UNIQUE INDEX (`order_id`)
    -> );
Query OK, 0 rows affected (0.84 sec)

show create table `t_order`;
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| TABLE   | CREATE TABLE                                                                                                                                                                                                                                                             |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_order | CREATE TABLE `t_order` (
        `x` int(11) NOT NULL AUTO_INCREMENT,
        `order_id` varchar(20) DEFAULT NULL,
        `seller_id` varchar(20) DEFAULT NULL,
        PRIMARY KEY (`x`),
        INDEX `i_0` (`seller_id`),
        UNIQUE INDEX `i_1` (`order_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

show full create table `t_order`;
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| TABLE   | CREATE TABLE          |
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_order | CREATE PARTITION TABLE `t_order` (
        `x` int(11) NOT NULL AUTO_INCREMENT,
        `order_id` varchar(20) DEFAULT NULL,
        `seller_id` varchar(20) DEFAULT NULL,
        PRIMARY KEY (`x`),
        GLOBAL INDEX /* i_0_$cff4 */ `i_0` (`seller_id`) PARTITION BY KEY (`seller_id`, `x`) PARTITIONS 16,
        UNIQUE GLOBAL INDEX /* i_1_$1782 */ `i_1` (`order_id`) PARTITION BY KEY (`order_id`) PARTITIONS 16,
        UNIQUE LOCAL KEY `_local_i_1` (`order_id`),
        LOCAL KEY `_local_i_0` (`seller_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`x`)
PARTITIONS 16
/* tablegroup = `tg8` */ |
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

自动分区规则

  • 如果目标表没有指定主键,PolarDB-X会启用隐式主键并将其作为拆分键,该主键为BIGINT类型的自增主键,且对用户不可见,使用show full create table可以查看完整的分区细节。
  • 如果目标表指定了主键,PolarDB-X会使用该主键作为拆分键。如果为复合主键,会使用复合主键的所有列作为拆分键。
  • 对于复合主键,按顺序作为KEY拆分方式的参数,如果遇到不支持的类型则跳过该列,如果第一列就不支持则会报错,必须手动指定为SINGLE表才能创建成功,SINGLE表建表语句参见单表与广播表
  • 自动分区使用分区表拆分算法,且拆分算法根据主键类型自动选择:
主键类型 拆分算法
bit, float, double, time, year, tinyblob, blob, mediumblob, longblob, enum, decimal, binary, varbinary, tinytext, text, mediumtext, longtext, set, geometry 不支持
其他 KEY分区

索引转换规则

主键拆分表上创建索引,除非明确指定为LOCAL索引,否则会自动转换为全局二级索引,具体转换规则如下:
  • 如果指定了LOCAL关键字,即强制指定索引为本地索引。
  • 对主键拆分表执行创建索引操作时,如果未指定LOCAL关键字,该操作将被自动地转变为创建无覆盖列(covering)的全局二级索引,并且索引列会依据上述的自动分区规则进行自动分区。如果需要建立普通的局部索引,您需要指定LOCAL关键字。
  • 在对全局二级索引生成拆分算法时,会使用全部的索引键进行拆分,同时,对于非UNIQUE约束,会附带上主键作为拆分算法参数。
  • 创建全局二级索引和聚簇索引时,会创建一个带 _local_ 前缀的本地索引。如果删除全局二级索引,PolarDB-X会自动同步删除对应的本地索引。
  • 主键拆分表可以不指定全局二级索引、聚簇索引的分区方式,PolarDB-X会根据自动分区原则对索引键执行分区。
下述语句及其注释为您展示了索引的转换规则。
CREATE PARTITION TABLE `t_order` (
    ->   `x` int,
    ->   `order_id` varchar(20) DEFAULT NULL,
    ->   `seller_id` varchar(20) DEFAULT NULL,
    ->   LOCAL INDEX `l_seller` using btree (`seller_id`), -- 强制指定为本地索引
    ->   UNIQUE LOCAL INDEX `l_order` using btree (`order_id`), -- 强制指定为本地唯一索引
    ->   INDEX `i_seller` using btree (`seller_id`), -- 会被替换为GSI,自动分区
    ->   UNIQUE INDEX `i_order` using btree (`order_id`), -- 会被替换为UGSI,自动分区
    ->   GLOBAL INDEX `g_seller` using btree (`seller_id`), -- 自动分区
    ->   UNIQUE GLOBAL INDEX `g_order` using btree (`order_id`), -- 自动分区
    ->   CLUSTERED INDEX `c_seller` using btree (`seller_id`), -- 自动分区聚簇
    ->   UNIQUE CLUSTERED INDEX `c_order` using btree (`order_id`) -- 自动分区聚簇
    -> );
Query OK, 0 rows affected (1.49 sec)

show create table `t_order`;
+---------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| TABLE   | CREATE TABLE                              |
+---------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_order | CREATE TABLE `t_order` (
        `x` int(11) DEFAULT NULL,
        `order_id` varchar(20) DEFAULT NULL,
        `seller_id` varchar(20) DEFAULT NULL,
        UNIQUE CLUSTERED INDEX `c_order` USING BTREE (`order_id`),
        CLUSTERED INDEX `c_seller` USING BTREE (`seller_id`),
        UNIQUE INDEX `g_order` USING BTREE (`order_id`),
        INDEX `g_seller` USING BTREE (`seller_id`),
        UNIQUE INDEX `i_order` USING BTREE (`order_id`),
        INDEX `i_seller` USING BTREE (`seller_id`),
        UNIQUE LOCAL KEY `l_order` USING BTREE (`order_id`),
        LOCAL KEY `l_seller` USING BTREE (`seller_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 |
+---------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

show full create table `t_order`;
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| TABLE   | CREATE TABLE                                                                                                                                                                                                  |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_order | CREATE PARTITION TABLE `t_order` (
        `x` int(11) DEFAULT NULL,
        `order_id` varchar(20) DEFAULT NULL,
        `seller_id` varchar(20) DEFAULT NULL,
        `_drds_implicit_id_` bigint(20) NOT NULL AUTO_INCREMENT,
        PRIMARY KEY (`_drds_implicit_id_`),
        UNIQUE CLUSTERED INDEX /* c_order_$1ba0 */ `c_order` USING BTREE (`order_id`) PARTITION BY KEY (`order_id`) PARTITIONS 16,
        CLUSTERED INDEX /* c_seller_$1e39 */ `c_seller` USING BTREE (`seller_id`) PARTITION BY KEY (`seller_id`, `_drds_implicit_id_`) PARTITIONS 16,
        UNIQUE GLOBAL INDEX /* g_order_$d57f */ `g_order` USING BTREE (`order_id`) PARTITION BY KEY (`order_id`) PARTITIONS 16,
        GLOBAL INDEX /* g_seller_$6ed5 */ `g_seller` USING BTREE (`seller_id`) PARTITION BY KEY (`seller_id`, `_drds_implicit_id_`) PARTITIONS 16,
        UNIQUE GLOBAL INDEX /* i_order_$ab2f */ `i_order` USING BTREE (`order_id`) PARTITION BY KEY (`order_id`) PARTITIONS 16,
        GLOBAL INDEX /* i_seller_$2b4b */ `i_seller` USING BTREE (`seller_id`) PARTITION BY KEY (`seller_id`, `_drds_implicit_id_`) PARTITIONS 16,
        UNIQUE LOCAL KEY `l_order` USING BTREE (`order_id`),
        UNIQUE LOCAL KEY `_local_i_order` USING BTREE (`order_id`),
        UNIQUE LOCAL KEY `_local_g_order` USING BTREE (`order_id`),
        UNIQUE LOCAL KEY `_local_c_order` USING BTREE (`order_id`),
        LOCAL KEY `l_seller` USING BTREE (`seller_id`),
        LOCAL KEY `_local_i_seller` USING BTREE (`seller_id`),
        LOCAL KEY `_local_g_seller` USING BTREE (`seller_id`),
        LOCAL KEY `_local_c_seller` USING BTREE (`seller_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
PARTITION BY KEY(`_drds_implicit_id_`)
PARTITIONS 16
/* tablegroup = `tg11` */ |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

主键拆分表的DDL限制

如需对主键拆分表执行下述DDL操作,存在一些限制。

DDL类别 DDL子句 说明与限制
CREATE INDEX
  • 如果使用了[UNIQUE] LOCAL INDEX子句,PolarDB-X将创建本地索引,且会自动同步到聚簇索引表中。
  • 如果使用了[UNIQUE] INDEX子句,PolarDB-X将其转换为对应的全局二级索引,同时,自动创建一个带_local_前缀的本地索引并同步到聚簇索引表中。
  • 如果使用了[UNIQUE] GLOBAL | CLUSTERED INDEX子句,PolarDB-X会自动创建一个带_local_前缀的本地索引并同步到聚簇索引表中。
    说明 如果未指定拆分方式则会自动拆分。
ALTER TABLE ADD {INDEX | KEY} [index_name] [index_type] (key_part,...) [index_option] ...
ADD [COLUMN] (col_name column_definition,...)
  • PolarDB-X将自动添加对应的列到聚簇全局二级索引(CGSI)和带唯一约束的聚簇全局二级索引(UCGSI)。
  • 支持回滚操作。
DROP [COLUMN] col_name 不允许删除主键、主表拆分键、索引表拆分键和复合UNIQUE约束中的列。
CHANGE [COLUMN] old_col_name new_col_name column_definition [FIRST | AFTER col_name]
  • 不允许重命名主键、主表拆分键、索引表拆分键。
  • 不允许重命名复合UNIQUE约束中的列。
    说明 其它列的限制可通过执行Hint:/*+TDDL: cmd_extra(ALLOW_LOOSE_ALTER_COLUMN_WITH_GSI=true)*/命令解除。更多信息,请参见如何使用HINT
  • 如果仅需修改default信息,推荐使用SET DEFAULT或DROP DEFAULT子句。
MODIFY [COLUMN] col_name column_definition [FIRST | AFTER col_name]
ALTER TABLE tbl_name ALTER [COLUMN] col_name { SET DEFAULT {literal | (expr)} | DROP DEFAULT } 支持回滚操作。
说明 如果列的默认值为current_timestamp,则不支持回滚操作。