首批通过分布式安全可靠测评,为关键业务系统打造
自动分区分裂
更新时间:2026-03-03 15:47:32
在 OceanBase 数据库中预先设定自动分区规则,在数据增长到一定程度时自动进行分区拆分操作。这样可以让数据库表在数据增长的情况下自动进行扩展,避免单分区数据量过大带来的负载均衡,性能等问题。
自动分区分裂操作的支持情况
当前版本仅支持对 Range 分区的一级分区有主键表支持自动分区能力。
使用限制及注意事项
- 不支持自动分裂 List、Hash 分区表。
- 不支持自动分裂二级分区表。
- 不支持被自动分裂的表的分区键与主键前缀不一样。
- 不支持无主键表的自动分区分裂。
- 不支持列存表的自动分区分裂。
- 不支持列存副本的自动分区分裂。
- 如果表所在的
TABLEGROUP(表组)里面包含了多张表时,不支持自动分区分裂;如果这个TABLEGROUP中只有这张表,则支持自动分区分裂。 - 不支持物化视图的自动分区分裂。
- 不支持全文索引的自动分裂。
- 不支持空间索引的自动分裂。
- 不支持向量索引的自动分区分裂。
- OceanBase 数据库支持 global_index_auto_split_policy 配置项,用于控制新建的全局索引是否开启自动分区功能。新建的全局索引如果开启了自动分区,会根据数据量重新生成分区规则,即预分裂。
基于表级别的自动分区配置
在 CREATE TABLE 时,通过配置 SIZE 子句创建单个自动分区表。
创建表时的自动分区语法
CREATE TABLE table_name (column_definition_list, PRIMARY KEY(column_name_list))
PARTITION BY RANGE([column_name_list]) [SIZE('size_value')]
[(range_partition_list)];
column_definition_list:
column_definition[, column_definition ...]
column_name_list:
column_name[, column_name ...]
range_partition_list:
PARTITION partition_name VALUES LESS THAN (value_list)[, PARTITION partition_name VALUES LESS THAN (value_list) ...]
value_list:
value[, value ...]
参数解释
| 参数 | 说明 |
|---|---|
| table_name | 指定表名。 |
| column_definition_list | 指定列定义列表,包括列名、数据类型、约束等。详细信息,参见 CREATE TABLE。 |
| PRIMARY KEY | 指定表的主键。 |
| PARTITION BY RANGE([column_name_list]) | 指定预分区键,当触发自动分区时,会将填写的预分区键作为实际的分区键(若 column_name_list 不填写,则使用主键为分区键)。 |
| SIZE('size_value') | 可选项,指定分区的分裂阈值。SIZE() 子句缺省时,默认读租户级别配置项 auto_split_tablet_size 的值。size_value 可取值 unlimited,表示分裂阈值无限制,不会分裂,后续不再调度新的自动分区分裂。 |
| range_partition_list | 可选项,预先创建分区位点(分区规则)。
注意当预先创建分区位点时,必须指定预分区键,否则报错。 |
修改表自动分区属性的语法
ALTER TABLE table_name
[MODIFY] PARTITION BY RANGE([column_name_list]) [SIZE('size_value')]
[(range_partition_list)];
column_name_list:
column_name[, column_name ...]
range_partition_list:
PARTITION partition_name VALUES LESS THAN (value_list)[, PARTITION partition_name VALUES LESS THAN (value_list) ...]
value_list:
value[, value ...]
说明
若在使用 ALTER TABLE ... PARTITION BY ... 语句时没有定义分区规则,则会采用 Online DDL 的方式修改表的自动分区属性,并且不影响原有的分区定义。
参数解释
| 参数 | 说明 |
|---|---|
| column_name_list | 修改非分区表的预分区键。在使用 ALTER TABLE 语句修改非分区表的自动分区属性时,若 RANGE() 内填写了预分区键信息,则会修改 Schema 中的相应记录;如果没有填写信息,则代表保持原有设定。 |
| SIZE('size_value') | 可选项,修改表的自动分区阈值。当 size_value 修改为 unlimited 时,不影响已有分区,后续不再调度新的自动分区分裂。 |
| range_partition_list | 可选项,修改分区规则。若未使用 SIZE 子句但又给定了分区定义,则仅修改分区规则,不影响原有的自动分区定义。
注意OceanBase 数据库 Oracle 模式暂不支持修改分区表的分区定义。 |
基于租户级别的自动分区配置
配置租户级配置项 enable_auto_split 和 auto_split_tablet_size,对租户下满足要求的表根据全局配置控制表的自动分裂。若在 CREATE TABLE 时省略了 SIZE 语法,则基于以下租户级别配置项决定是否创建自动分区表(默认使用主键列作为自动分区表的分区键)。
- enable_auto_split:租户级别配置项,控制租户是否开启自动分区功能。
- auto_split_tablet_size:租户级别配置项,控制租户开启自动分区功能之后触发分裂的阈值。
如果省略了 SIZE 语法,并且设置 enable_auto_split 为 true,仅会为符合分裂限制的表设置自动分区,不会对不符合分裂限制的表生效。例如,当创建二级分区表、非 Range 分区表、无主键表或分区键与主键前缀不一致的分区表时,会正常创建为非自动分区表(若用户手动写了自动分区的特殊语法则依然会报错)。
说明
可以使用视图 sys.ALL_TABLES/sys.DBA_TABLES/sys.USER_TABLES 或者在系统租户中使用 oceanbase.CDB_TABLES 查看表的自动分区属性。
自动分区的行为说明
自动分区 DDL 操作
- 修改分区规则:只支持修改为一级分区按照主键 Range 分区,其他的分区规则修改不支持。
- 修改主键:要求修改主键后自动分区键是主键前缀。
- 列操作:预分区键的操作限制等同于分区键。
说明
其余 DDL 操作与非自动分区表要求一致。
DML 行为
分裂过程中相当于分裂前后两种 Schema 共存,源和目的分区的 DML 行为上相当于操作同一份数据,如源分区的写入和查询会尽量转换成对应目的分区的查询和写入,对于目的分区的写入和查询会感知源分区转发过来的写入,具体如下:
| N/A | 指定源分区的 DML(INSERT INTO t1 PARTITION(p0) ...) | 涉及源分区的 DML(SELECT * FROM t1) | 指定目的分区的 DML | 涉及目的分区的 DML |
|---|---|---|---|---|
| 分裂开启事务前 | 正常 | 正常 | 报错,行为同操作不存在的分区 | 无此情况 |
| 分裂过程中 | 可能报错,报错时行为同操作不存在的分区 | 不报错,内部进行写入的切流和查询的语句重试 | 正常 | 正常 |
| 分裂结束事务后 | 报错,行为同操作不存在的分区 | 无此情况 | 正常 | 正常 |
示例
示例一:创建表级别的自动分区表
关闭自动分区功能。
AlTER SYSTEM SET enable_auto_split = FALSE;说明
可以使用
SHOW PARAMETERS LIKE 'enable_auto_split';查看自动分区功能是否开启。创建自动分区表
test1_tbl1,不指定预分区键,指定分裂阈值为 10GB。CREATE TABLE test1_tbl1 (col1 NUMBER, col2 NUMBER, col3 VARCHAR2(30), PRIMARY KEY(col1, col2)) PARTITION BY RANGE() SIZE('10GB');创建自动分区表
test1_tbl2,指定预分区键为col1,指定分裂阈值为 10GB。CREATE TABLE test1_tbl2 (col1 NUMBER, col2 NUMBER, col3 VARCHAR2(30), PRIMARY KEY(col1, col2)) PARTITION BY RANGE(col1) SIZE('10GB');创建自动分区表
test1_tbl3,不指定预分区键和分裂阈值(分裂阈值会默认使用auto_split_tablet_size的值)。CREATE TABLE test1_tbl3 (col1 NUMBER, col2 NUMBER, col3 VARCHAR2(30), PRIMARY KEY(col1, col2)) PARTITION BY RANGE();创建自动分区表
test1_tbl4时,指定预分区键为col1, col2,分裂阈值为 10GB,并预先创建分区位点P0、P1、P2和P3。CREATE TABLE test1_tbl4 (col1 NUMBER, col2 NUMBER, col3 VARCHAR2(30), PRIMARY KEY(col1, col2)) PARTITION BY RANGE(col1, col2) SIZE('10GB') (PARTITION P0 VALUES LESS THAN (100, MAXVALUE), PARTITION P1 VALUES LESS THAN (500, MAXVALUE), PARTITION P2 VALUES LESS THAN (800, MAXVALUE), PARTITION P3 VALUES LESS THAN (MAXVALUE, MAXVALUE));查看表的自动分区属性。
SELECT OWNER, TABLE_NAME, AUTO_SPLIT, AUTO_SPLIT_TABLET_SIZE FROM sys.ALL_TABLES WHERE TABLE_NAME LIKE 'TEST1%' ORDER BY TABLE_NAME;返回结果如下:
+-------+------------+------------+------------------------+ | OWNER | TABLE_NAME | AUTO_SPLIT | AUTO_SPLIT_TABLET_SIZE | +-------+------------+------------+------------------------+ | SYS | TEST1_TBL1 | TRUE | 10737418240 | | SYS | TEST1_TBL2 | TRUE | 10737418240 | | SYS | TEST1_TBL3 | TRUE | 134217728 | | SYS | TEST1_TBL4 | TRUE | 10737418240 | +-------+------------+------------+------------------------+ 4 rows in set
示例二:修改表自动分区属性
创建自动分区表
test2_tbl1,指定预分区键为col1,指定分裂阈值为 10GB。CREATE TABLE test2_tbl1 (col1 NUMBER, col2 NUMBER, col3 VARCHAR2(30), PRIMARY KEY(col1, col2)) PARTITION BY RANGE(col1) SIZE('10GB');修改表
test2_tbl1的自动分区阈值为 1GB。ALTER TABLE test2_tbl1 PARTITION BY RANGE() SIZE('1GB');或
ALTER TABLE test2_tbl1 PARTITION BY RANGE(col1) SIZE('1GB');创建自动分区表
test2_tbl2,指定预分区键为col1,指定分裂阈值为 10GB。CREATE TABLE test2_tbl2 (col1 NUMBER, col2 NUMBER, col3 VARCHAR2(30), PRIMARY KEY(col1, col2)) PARTITION BY RANGE(col1) SIZE('10GB');表
test2_tbl2添加分区位点p0(值小于 100 的行)、p1(值大于等于 100 且小于 200 的行)和p_max(大于等于 200 的行)。ALTER TABLE test2_tbl2 PARTITION BY RANGE(col1) SIZE('10GB') (PARTITION p0 VALUES LESS THAN(100), PARTITION p1 VALUES LESS THAN(200), PARTITION p_max VALUES LESS THAN (MAXVALUE));创建自动分区表
test2_tbl3,指定预分区键为col1,指定分裂阈值为 10GB。CREATE TABLE test2_tbl3 (col1 NUMBER, col2 NUMBER, col3 VARCHAR2(30), PRIMARY KEY(col1, col2)) PARTITION BY RANGE(col1) SIZE('10GB');禁止表
test2_tbl3进行自动分区,修改后不影响已有分区,后续不再调度新的自动分区分裂。ALTER TABLE test2_tbl3 PARTITION BY RANGE() SIZE('unlimited');创建自动分区表
test2_tbl4,指定预分区键为col1,指定分裂阈值为 10GB。CREATE TABLE test2_tbl4 (col1 NUMBER, col2 NUMBER, col3 VARCHAR2(30), PRIMARY KEY(col1, col2)) PARTITION BY RANGE(col1) SIZE('10GB');将表
test2_tbl4的预分区键由col1改成col1,col2。ALTER TABLE test2_tbl4 PARTITION BY RANGE (col1,col2) SIZE('10GB');创建非自动分区表
test2_tbl5。CREATE TABLE test2_tbl5 (col1 NUMBER, col2 NUMBER, col3 VARCHAR2(30), PRIMARY KEY(col1, col2));不指定
SIZE子句将表test2_tbl5改为自动分区表,分裂阈值会默认使用auto_split_tablet_size的值。ALTER TABLE test2_tbl5 PARTITION BY RANGE (col1);查看表的自动分区属性。
SELECT OWNER, TABLE_NAME, AUTO_SPLIT, AUTO_SPLIT_TABLET_SIZE FROM sys.ALL_TABLES WHERE TABLE_NAME LIKE 'TEST2%' ORDER BY TABLE_NAME;返回结果如下:
+-------+------------+------------+------------------------+ | OWNER | TABLE_NAME | AUTO_SPLIT | AUTO_SPLIT_TABLET_SIZE | +-------+------------+------------+------------------------+ | SYS | TEST2_TBL1 | TRUE | 1073741824 | | SYS | TEST2_TBL2 | TRUE | 10737418240 | | SYS | TEST2_TBL3 | FALSE | 0 | | SYS | TEST2_TBL4 | TRUE | 10737418240 | | SYS | TEST2_TBL5 | TRUE | 134217728 | +-------+------------+------------+------------------------+ 5 rows in set
示例三:开启自动分区功能后创建表
开启自动分区功能。
AlTER SYSTEM SET enable_auto_split = TRUE;创建非分区表
test3_tbl1。因为租户级别设置了所有非分区表格自动使用 SIZE 分区,那么下面这个正常创建表的语法会做自动分区,读租户级配置项。CREATE TABLE test3_tbl1 (col1 INT, col2 INT, PRIMARY KEY(col1));创建自动分区的非分区表
test3_tbl2。因为没有指定分区键,所以会默认使用主键为分区键。CREATE TABLE test3_tbl2 (col1 INT, col2 INT, PRIMARY KEY(col1)) PARTITION BY RANGE ();创建自动分区的非分区表
test3_tbl3(分裂阈值为 1024MB,使用用户配置)。CREATE TABLE test3_tbl3 (col1 INT, col2 INT, PRIMARY KEY(col1)) PARTITION BY RANGE () SIZE('1024MB');创建非自动分区表
test3_tbl4。CREATE TABLE test3_tbl4 (col1 INT, col2 INT, PRIMARY KEY(col1)) PARTITION BY RANGE () SIZE('unlimited');无主键表不符合自动分区要求,即使
enable_auto_split = true也不开启自动分区。CREATE TABLE test3_tbl5 (col1 INT, col2 INT);无主键表不符合自动分区要求,手动开启自动分区会报错。
CREATE TABLE test3_tbl6 (col1 INT, col2 INT) PARTITION BY RANGE ();返回结果如下:
OBE-00600: internal error code, arguments: -4007, auto partitioned table without primary key is not supported查看表的自动分区属性。
SELECT OWNER, TABLE_NAME, AUTO_SPLIT, AUTO_SPLIT_TABLET_SIZE FROM sys.ALL_TABLES WHERE TABLE_NAME LIKE 'TEST3%' ORDER BY TABLE_NAME;返回结果如下:
+-------+------------+------------+------------------------+ | OWNER | TABLE_NAME | AUTO_SPLIT | AUTO_SPLIT_TABLET_SIZE | +-------+------------+------------+------------------------+ | SYS | TEST3_TBL1 | TRUE | 134217728 | | SYS | TEST3_TBL2 | TRUE | 134217728 | | SYS | TEST3_TBL3 | TRUE | 1073741824 | | SYS | TEST3_TBL4 | FALSE | 0 | | SYS | TEST3_TBL5 | FALSE | 0 | +-------+------------+------------+------------------------+ 5 rows in set
示例四:全局索引开启自动分区
说明
对于开启自动分区的表,即使配置项 global_index_auto_split_policy 未启用,创建的全局索引仍会自动分区。
创建自动分区表
test4_tbl1(分裂阈值为 1024MB,使用用户配置)。CREATE TABLE test4_tbl1 (col1 INT, col2 INT, col3 INT, PRIMARY KEY(col1)) PARTITION BY RANGE () SIZE('1024MB');在表
test4_tbl1上创建全局索引idx1_test4_tbl1。CREATE INDEX idx1_test4_tbl1 ON test4_tbl1 (col2) GLOBAL;开启自动分区功能。
ALTER SYSTEM SET global_index_auto_split_policy = 'ALL';创建非自动分区的分区表
test4_tbl2。CREATE TABLE test4_tbl2(col1 INT, col2 INT, col3 INT, PRIMARY KEY(col1)) PARTITION BY RANGE(col1) (PARTITION p0 VALUES LESS THAN(100), PARTITION p1 VALUES LESS THAN(200), PARTITION p2 VALUES LESS THAN(300));在表
test4_tbl2上创建全局索引idx1_test4_tbl2。CREATE INDEX idx1_test4_tbl2 ON test4_tbl2 (col2) GLOBAL;