首批通过分布式安全可靠测评,为关键业务系统打造
分区交换
更新时间:2026-06-18 10:13:19
OceanBase 数据库的分区交换功能主要用来实现快速将数据导入分区表,达到数据高效加载的目的,即通过全量旁路导入的方式将数据快速导入新建非分区表中,然后利用分区交换功能将非分区表中的数据快速导入分区表中,加快现有分区表增量数据导入的性能。
可以考虑将分区交换功能作为增量旁路导入的备选方案。例如,基于分区交换功能来导入分区表 A 的增量数据,具体操作步骤如下:
- 在表 A 上创建一个空的新分区 P。
- 新建一张结构与表 A 完全相同的非分区表 B,并通过旁路导入将增量数据导入至表 B。
- 利用分区交换功能,将表 A 中的新分区 P 与表 B 进行互换。
分区交换的支持情况
分区交换的支持情况如下表所示,其中类型的列代表目标表(target_partition_table_name),类型的行代表源表(origin_table_name)。
| 类型 | 非分区表 | 一级分区表 | 二级分区表 |
|---|---|---|---|
| 一级分区表 | 支持 | 不支持 | 不支持 |
| 二级分区表的一级分区 | 不支持 | 支持 | 不支持 |
| 二级分区表的二级分区 | 支持 | 不支持 | 不支持 |
使用限制及注意事项
不支持数据校验,即必须指定
WITHOUT VALIDATION,用户需要自行保证交换数据的有效性。分区表和非分区表的表级和列级属性要求一一对应。
分区表和非分区表的约束要求完全相同,且当前版本不支持两表存在外键约束。
分区表的局部索引表和非分区表的索引表要求一一对应。
在 MySQL 模式下,分区交换要求源表与目标表的索引定义保持一致(包括索引名称、类型、列及其顺序)。当前 OceanBase 数据库尚无法识别以下不一致情形:
- 前缀索引的前缀长度不同。
- 虚拟生成列的表达式不一致。
说明
对于 OceanBase 数据库可识别到源表与目标表的索引的不一致场景,分区交换操作将被拒绝执行;对于上述未覆盖的场景,可能存在校验遗漏,建议您在使用时确保索引定义完全一致,以避免潜在的数据或查询异常。
只支持
INCLUDING INDEXES的行为(MySQL 模式默认包含INCLUDING INDEXES行为),局部索引对应分区的数据也会参与交换,局部索引在交换后保持交换前的可用状态。不支持
UPDATE GLOBAL INDEXES,因此全局索引在交换成功后都会是 Unusable 状态(无效状态)。当前的分区交换功能建议只作为增量旁路导入的临时替换功能。有关增量旁路导入的信息,参见 旁路导入概述。
当使用一级分区表与非分区表交换数据时:
- 一级分区必须是 Range/Range columns/List 分区。
当使用二级分区表的二级分区与非分区表交换数据时:
- 对一级分区类型没有要求,不过二级分区必须是 Range/Range columns 分区。
当使用二级分区表的一级分区与一级分区表交换数据时:
target_partition_table_name必须是二级分区表,指定交换的分区必须是该表的某个一级分区名。且该二级分区表的一级分区必须是 Range/Range Columns/List/List Columns 分区。origin_table_name必须是一级分区表,其分区类型必须与用于交换的一级分区下的二级分区完全一致。- 一二级分区表交换后,相关表的统计信息会失效,需要重新搜集。
语法
ALTER TABLE target_partition_table_name
EXCHANGE PARTITION partition_name
WITH TABLE origin_table_name
WITHOUT VALIDATION;
参数解释
| 参数 | 描述 |
|---|---|
| target_partition_table_name | 表示分区交换中目标分区表名称。 |
| partition_name | 表示分区交换中目标分区表的分区名称。 |
| origin_table_name | 表示分区交换中源表名称,为非分区表或一级分区表。 |
使用说明
当前分区交换功能实现一张分区表的一个分区和非分区表做数据交换,主要作为增量旁路导入功能的临时替换工具,其中分区表和非分区表通常特性如下:
- 分区表(partitioned table):包含历史数据的分区表,通常数据量较大。
- 非分区表(non-partitioned table):包含增量数据。
分区交换功能的使用须极为小心,因为不当操作可引起数据不符合原表分区键的条件,进而触发连锁错误。因此,在执行分区交换时,该按照以下步骤来判断分区表与非分区表是否能够进行分区交换。
使用
SHOW CREATE TABLE语句查询分区表的分区键以及目标分区信息。查询非分区表的数据,判断非分区表的数据是否满足目标分区分区键数据范围要求。其中
table_name为要查询的表名。SHOW CREATE TABLE table_name;通过查询结果,保证分区表和非分区表符合上述 使用限制及注意事项。
在进行分区交换之前,至少需要确保以下条件符合要求。
属性 要求 是否在同一租户下 是 是否在同一个 Database 下 否,兼容 MySQL,支持跨数据库交换 是否同一表组(TableGroup) 是 是否同一表空间(TableSpace) 是 使用的字符集格式是否一致 是 表类型是否一致 是,要求都是用户表,即 USER_TABLE主键数量是否一致 是 行存储格式是否一致 是 列格式和列的相对顺序是否一致 是 是否都是自增列 是 列的默认值、生成列表达式是否一致 是 加密方式是否一致 是 列存格式是否一致 是 索引格式、状态和数量是否一致 是,分区表的局部索引需要和非分区表的索引一一对应 索引表名是否一致 是,兼容 MySQL,相同表名的索引定义一一对应 约束格式、包含的列是否一致 是 使用分区交换的语法进行分区交换,交换之后,分区表指定分区的数据会迁移到非分区表上,非分区表的数据会迁移到分区表的指定分区上。分区表的全局索引状态为 Unusable。
示例
示例一:一级分区表与非分区表交换数据
Range 一级分区表与非分区表交换数据。
创建 Range 一级分区表
tbl1_r。obclient> CREATE TABLE tbl1_r (col1 INT PRIMARY KEY, col2 VARCHAR(50)) PARTITION BY RANGE(col1) (PARTITION p0 VALUES LESS THAN(10), PARTITION p1 VALUES LESS THAN(20), PARTITION p2 VALUES LESS THAN(30) );创建非分区表
tbl1。obclient> CREATE TABLE tbl1 (col1 INT PRIMARY KEY, col2 VARCHAR(50));向表
tbl1中插入数据。obclient> INSERT INTO tbl1 VALUES(1, 'a1'),(2, 'a2');返回结果如下:
Query OK, 2 rows affected Records: 2 Duplicates: 0 Warnings: 0执行分区表
tbl1_r的分区p0与非分区表tbl1进行分区交换。obclient> ALTER TABLE tbl1_r EXCHANGE PARTITION p0 WITH TABLE tbl1 WITHOUT VALIDATION;查看分区表
tbl1_r的分区p0的数据。obclient> SELECT * FROM tbl1_r PARTITION(p0);返回结果如下:
+------+------+ | col1 | col2 | +------+------+ | 1 | a1 | | 2 | a2 | +------+------+ 2 rows in set
List 一级分区表与非分区表交换数据。
创建 List 一级分区表
tbl1_l。obclient> CREATE TABLE tbl1_l (col1 INT, col2 VARCHAR(50), col3 INT) PARTITION BY LIST(col3) (PARTITION p0 VALUES IN (1, 2, 3, 4), PARTITION p1 VALUES IN (5, 6, 7, 8, 9), PARTITION p2 VALUES IN (DEFAULT) );创建非分区表
tbl1_2。obclient> CREATE TABLE tbl1_2 (col1 INT, col2 VARCHAR(50), col3 INT);向表
tbl1_2中插入数据。obclient> INSERT INTO tbl1_2 VALUES(1, 'a1', 1), (2, 'a2', 2), (3, 'a3', 3), (4, 'a4', 4), (5, 'a5', 5);返回结果如下:
Query OK, 5 rows affected Records: 5 Duplicates: 0 Warnings: 0执行分区表
tbl1_l的分区p0与非分区表tbl1_2进行分区交换。obclient> ALTER TABLE tbl1_l EXCHANGE PARTITION p0 WITH TABLE tbl1_2 WITHOUT VALIDATION;查看分区表
tbl1_l的分区p0的数据。obclient> SELECT * FROM tbl1_l PARTITION(p0);返回结果如下:
+------+------+------+ | col1 | col2 | col3 | +------+------+------+ | 1 | a1 | 1 | | 2 | a2 | 2 | | 3 | a3 | 3 | | 4 | a4 | 4 | | 5 | a5 | 5 | +------+------+------+ 5 rows in set
示例二:二级分区表的一级分区与一级分区表交换数据
创建 Range + Hash 二级分区表
tbl2_rh。obclient> CREATE TABLE tbl2_rh (col1 INT PRIMARY KEY, col2 INT) PARTITION BY RANGE(col1) SUBPARTITION BY HASH(col1) SUBPARTITIONS 5 (PARTITION p0 VALUES LESS THAN (10), PARTITION p1 VALUES LESS THAN (20), PARTITION p2 VALUES LESS THAN (30), PARTITION p3 VALUES LESS THAN (MAXVALUE) );创建 Hash 一级分区表
tbl2_h。obclient> CREATE TABLE tbl2_h (col1 INT PRIMARY KEY, col2 INT) PARTITION BY HASH(col1) PARTITIONS 5;向表
tbl2_rh中插入数据。obclient> INSERT INTO tbl2_rh VALUES(11, 30), (14, 40), (26, 150), (29, 160);返回结果如下:
Query OK, 4 rows affected Records: 4 Duplicates: 0 Warnings: 0查看分区表
tbl2_rh的分区p1的数据。obclient> SELECT * FROM tbl2_rh PARTITION(p1);返回结果如下:
+------+------+ | col1 | col2 | +------+------+ | 11 | 30 | | 14 | 40 | +------+------+ 2 rows in set向表
tbl2_h中插入数据。obclient> INSERT INTO tbl2_h VALUES(12, 20), (16, 110), (17, 170), (19, 120);返回结果如下:
Query OK, 4 rows affected Records: 4 Duplicates: 0 Warnings: 0执行二级分区表
tbl2_rh的分区p1与一级分区表tbl2_h进行分区交换。obclient> ALTER TABLE tbl2_rh EXCHANGE PARTITION p1 WITH TABLE tbl2_h WITHOUT VALIDATION;查看分区表
tbl2_rh的分区p1的数据。obclient> SELECT * FROM tbl2_rh PARTITION(p1);返回结果如下:
+------+------+ | col1 | col2 | +------+------+ | 16 | 110 | | 12 | 20 | | 17 | 170 | | 19 | 120 | +------+------+ 4 rows in set
示例三:二级分区表的二级分区与非分区表交换数据
创建 Range + Range 二级分区表
tbl3_rr。obclient> CREATE TABLE tbl3_rr(col1 INT, col2 INT) PARTITION BY RANGE(col1) SUBPARTITION BY RANGE(col2) (PARTITION p0 VALUES LESS THAN(10) (SUBPARTITION sp0 VALUES LESS THAN(20), SUBPARTITION sp1 VALUES LESS THAN(50), SUBPARTITION sp2 VALUES LESS THAN (MAXVALUE) ), PARTITION p1 VALUES LESS THAN(20) (SUBPARTITION sp3 VALUES LESS THAN(20), SUBPARTITION sp4 VALUES LESS THAN(50), SUBPARTITION sp5 VALUES LESS THAN (MAXVALUE) ) );创建非分区表
tbl3。obclient> CREATE TABLE tbl3 (col1 INT, col2 INT);向表
tbl3_rr中插入数据。obclient> INSERT INTO tbl3_rr VALUES(1, 10), (4, 15), (6, 12), (19, 160);返回结果如下:
Query OK, 4 rows affected Records: 4 Duplicates: 0 Warnings: 0查看分区表
tbl3_rr的分区sp0的数据。obclient> SELECT * FROM tbl3_rr PARTITION(sp0);返回结果如下:
+------+------+ | col1 | col2 | +------+------+ | 1 | 10 | | 4 | 15 | | 6 | 12 | +------+------+ 3 rows in set向表
tbl3中插入数据。obclient> INSERT INTO tbl3 VALUES(2, 20), (3, 10), (5, 17), (8, 12);返回结果如下:
Query OK, 4 rows affected Records: 4 Duplicates: 0 Warnings: 0执行二级分区表
tbl3_rr的分区sp0与一级分区表tbl3进行分区交换。obclient> ALTER TABLE tbl3_rr EXCHANGE PARTITION sp0 WITH TABLE tbl3 WITHOUT VALIDATION;查看分区表
tbl3_rr的分区sp0的数据。obclient> SELECT * FROM tbl3_rr PARTITION(sp0);返回结果如下:
+------+------+ | col1 | col2 | +------+------+ | 2 | 20 | | 3 | 10 | | 5 | 17 | | 8 | 12 | +------+------+ 4 rows in set