在 OceanBase 数据库 V4.0 到 V4.2 版本中,删列操作采用的是完全重写数据的 Offline DDL 方式,耗时较长。从 OceanBase 数据库 V4.2.1 BP4 版本开始,Oracle 模式租户下删列操作改成默认打标删除的方式,以解决 OceanBase 数据库 V4.x 版本中删列性能回退的问题。本文主要介绍快速删除列特性带来的一些视图和运维操作上的变化。
详细说明
OceanBase 数据库 Oracle 模式从 V4.2.1 BP4 版本开始,只支持快速删除列(不支持非快速删除列)。
相应的语法如下:
ALTER TABLE <表名> DROP COLUMN <列名>;具体示例如下:
obclient [SYS]> CREATE TABLE t1 (id INT,name VARCHAR2(10)); Query OK, 0 rows affected (0.169 sec) obclient [SYS]> ALTER TABLE t1 DROP COLUMN name; Query OK, 0 rows affected (0.601 sec) obclient [SYS]> DESC t1; +-------+------------+------+------+---------+-------+ | FIELD | TYPE | NULL | KEY | DEFAULT | EXTRA | +-------+------------+------+------+---------+-------+ | ID | NUMBER(38) | YES | NULL | NULL | NULL | +-------+------------+------+------+---------+-------+ 1 row in set (0.014 sec)说明
在原生 Oracle 中,既支持永久删列,语法也是:
ALTER TABLE <表名> DROP COLUMN <列名>;也支持快速删列,语法是:ALTER TABLE <表名> SET UNUSED COLUMN <列名>;OceanBase 数据库 Oracle 模式对于快速删除的列和原生 Oracle 的
ALL_TAB_COLS视图都会显示为SYS_C[COLUMN_ID]_TIME$(例如:SYS_C00002_24041819:01:29$),如果用户不想在相关系统视图的查询结果中返回已经快速删除的列,需要用户自己去过滤处理下(过滤方法:快速删的列USER_GENERATED='NO')。目前 OceanBase 数据库 Oracle 模式和原生 Oracle 的ALL_TAB_COLUMNS/DBA_TAB_COLUMNS/USER_TAB_COLUMNS视图都不包含快速删除列,建议正常使用这三个标准视图来进行系统元数据的查询。具体示例如下:
obclient [SYS]> SELECT * FROM DBA_TAB_COLS WHERE TABLE_NAME = 'T1' AND OWNER = 'SYS'\G *************************** 1. row *************************** OWNER: SYS TABLE_NAME: T1 COLUMN_NAME: ID DATA_TYPE: NUMBER DATA_TYPE_MOD: NULL DATA_TYPE_OWNER: NULL DATA_LENGTH: 22 DATA_PRECISION: NULL DATA_SCALE: 0 NULLABLE: Y COLUMN_ID: 16 DEFAULT_LENGTH: NULL DATA_DEFAULT: NULL NUM_DISTINCT: NULL LOW_VALUE: NULL HIGH_VALUE: NULL DENSITY: NULL NUM_NULLS: NULL NUM_BUCKETS: NULL LAST_ANALYZED: NULL SAMPLE_SIZE: NULL CHARACTER_SET_NAME: NULL CHAR_COL_DECL_LENGTH: NULL GLOBAL_STATS: NULL USER_STATS: NULL AVG_COL_LEN: NULL CHAR_LENGTH: 0 CHAR_USED: NULL V80_FMT_IMAGE: NULL DATA_UPGRADED: NULL HIDDEN_COLUMN: NO VIRTUAL_COLUMN: NO SEGMENT_COLUMN_ID: NULL INTERNAL_COLUMN_ID: NULL HISTOGRAM: NULL QUALIFIED_COL_NAME: ID USER_GENERATED: YES DEFAULT_ON_NULL: NULL IDENTITY_COLUMN: NULL EVALUATION_EDITION: NULL UNUSABLE_BEFORE: NULL UNUSABLE_BEGINNING: NULL COLLATION: NULL COLLATED_COLUMN_ID: NULL *************************** 2. row *************************** OWNER: SYS TABLE_NAME: T1 COLUMN_NAME: SYS_C00017_24082811:52:14$ DATA_TYPE: VARCHAR2 DATA_TYPE_MOD: NULL DATA_TYPE_OWNER: NULL DATA_LENGTH: 10 DATA_PRECISION: NULL DATA_SCALE: NULL NULLABLE: Y COLUMN_ID: 17 DEFAULT_LENGTH: NULL DATA_DEFAULT: NULL NUM_DISTINCT: NULL LOW_VALUE: NULL HIGH_VALUE: NULL DENSITY: NULL NUM_NULLS: NULL NUM_BUCKETS: NULL LAST_ANALYZED: NULL SAMPLE_SIZE: NULL CHARACTER_SET_NAME: CHAR_CS CHAR_COL_DECL_LENGTH: NULL GLOBAL_STATS: NULL USER_STATS: NULL AVG_COL_LEN: NULL CHAR_LENGTH: 10 CHAR_USED: B V80_FMT_IMAGE: NULL DATA_UPGRADED: NULL HIDDEN_COLUMN: NO VIRTUAL_COLUMN: NO SEGMENT_COLUMN_ID: NULL INTERNAL_COLUMN_ID: NULL HISTOGRAM: NULL QUALIFIED_COL_NAME: SYS_C00017_24082811:52:14$ USER_GENERATED: NO DEFAULT_ON_NULL: NULL IDENTITY_COLUMN: NULL EVALUATION_EDITION: NULL UNUSABLE_BEFORE: NULL UNUSABLE_BEGINNING: NULL COLLATION: NULL COLLATED_COLUMN_ID: NULL 2 rows in set (0.055 sec) obclient> select * from dba_tab_columns where table_name='T1' and owner='SYS'\G *************************** 1. row *************************** OWNER: SYS TABLE_NAME: T1 COLUMN_NAME: ID DATA_TYPE: NUMBER DATA_TYPE_MOD: NULL DATA_TYPE_OWNER: NULL DATA_LENGTH: 22 DATA_PRECISION: NULL DATA_SCALE: 0 NULLABLE: Y COLUMN_ID: 16 DEFAULT_LENGTH: NULL DATA_DEFAULT: NULL NUM_DISTINCT: NULL LOW_VALUE: NULL HIGH_VALUE: NULL DENSITY: NULL NUM_NULLS: NULL NUM_BUCKETS: NULL LAST_ANALYZED: NULL SAMPLE_SIZE: NULL CHARACTER_SET_NAME: NULL CHAR_COL_DECL_LENGTH: NULL GLOBAL_STATS: NULL USER_STATS: NULL AVG_COL_LEN: NULL CHAR_LENGTH: 0 CHAR_USED: NULL V80_FMT_IMAGE: NULL DATA_UPGRADED: NULL HISTOGRAM: NULL DEFAULT_ON_NULL: NULL IDENTITY_COLUMN: NULL EVALUATION_EDITION: NULL UNUSABLE_BEFORE: NULL UNUSABLE_BEGINNING: NULL COLLATION: NULL 1 row in set (0.057 sec)原生 Oracle 中已标记快速删除的列在
ALL_TAB_COLS视图中对应的HIDDEN_COLUM字段为 YES,而 OceanBase 数据库 Oracle 模式中ALL_TAB_COLS视图中已标记快速删除列对应的HIDDEN_COLUMN字段为 NO。OceanBase 数据库 Oracle 模式中:

原生 Oracle 中:

快速删列后对应的被删列的列名会被修改为
SYS_(ORIG_COLUMN_ID)_TIME$,允许创建名为ORIG_COLUMN_NAME的同名新列。因为快速删列只是将对应的列从逻辑上删除,但其在存储层没有被立刻删除,因此 备份恢复/迁移复制/Transfer 都会带着被快速删除的列。目前快速删列后在
ALL_TAB_COLS、DBA_TAB_COLS、USER_TAB_COLS和CDB_TAB_COLS这四张 OceanBase 数据库中已有的视图中还会展示逻辑删除列的列信息。其中UNUSED列对应的字段USER_GENERATED='NO'。
OceanBase 数据库 Oracle 模式会限制表中同时存在的标记删除列的个数,当前的阈值为 128。当一张表包含的逻辑删除行列的数目达到 128 列时,会导致下一次快速加列/删列的 DDL SQL 执行时报错
The number of obsolete cloumns reaches the limit. Use "alter table <table_name> force;" to defragment first...”,此时用户需要先执行清理列操作。具体报错信息如下。ORA-00600: internal error code, arguments: -4179, The number of obsolete columns reaches the limit. Use "alter table table_name force" to defragment first,otherwise dropping column is not allowedOceanBase 数据库 Oracle 模式中已标记删除的列需要等待执行
Offline DDL(如修改主键)、TRUNCATE TABLE或者手动执行ALTER TABLE <table_name> FORCE才会真正从存储层实际删除。目前执行合并操作也不会将标记删除的列真正从存储层实际删除。
影响版本
影响 OceanBase 数据库中的 Oracle 租户,对于 SYS 租户和 MySQL 租户无影响。
适用版本
OceanBase 数据 V4.2.1 BP4(oceanbase-4.2.1.4-104000062024022914)及之后版本。