
准备测试表、数据、索引等(源表信息)
1、创建测试表TEST,表结构如下,使用范围分区,LOGTIME为分区列,SQL参考如下:
drop table if EXISTS TEST;CREATE TABLE TEST ("LOGTIME" TIMESTAMP(0) NOT NULL,"TASKID" int,"TASKNAME" varchar(30))PARTITION BY RANGE("LOGTIME")(PARTITION "PART05" VALUES LESS THAN(DATETIME'2024-05-01 00:00:00'),PARTITION "PART06" VALUES LESS THAN(DATETIME'2024-06-01 00:00:00'),PARTITION "PART07" VALUES LESS THAN(DATETIME'2024-07-01 00:00:00'),PARTITION "PART08" VALUES LESS THAN(DATETIME'2024-08-01 00:00:00'),PARTITION "PART09" VALUES LESS THAN(DATETIME'2024-09-01 00:00:00'),PARTITION "PART10" VALUES LESS THAN(DATETIME'2024-10-01 00:00:00'),PARTITION "PART11" VALUES LESS THAN(DATETIME'2024-11-01 00:00:00'))tablespace main;
2、插入测试数据:
insert into TEST(LOGTIME, taskid, taskname)select sysdate -rownum/20, rownum, DBMS_RANDOM.STRING('a', 30)from dualconnect by rownum <=100000;commit;
3、创建索引(表空间创建略):
create index ix_test_name on test(TASKNAME) tablespace dmidx;
创建中间表(目标表结构)
创建目标表,即创建一张中间表,表结构和分区是在线重定义后的目标表结构及分区。
比如我们要将上面TEST表的表结构修改为interval分区,并增加列。
我们创建中间表TEST_TMP(TEST_TMP表使用了interval分区;modifydate列为新增列;使用新的表空间DMDATA),表结构SQL参考如下:
drop table if EXISTS TEST_TMP;CREATE TABLE TEST_TMP(LOGTIME TIMESTAMP(0) NOT NULL,TASKID int,TASKNAME varchar(30),modifydate DATETIME DEFAULT sysdate)PARTITION BY RANGE(LOGTIME)INTERVAL(numtoyminterval(1,'month'))(PARTITION "P1" VALUES LESS THAN(DATETIME'2024-03-01 00:00:00'))tablespace DMDATA;
在线重定义
1、判断原表是否可以重定义(可选)
调用CAN_REDEF_TABLE判断源表是否可以重定义。
注意因为TEST表没有主键,这里只能指定OPTIONS_FLAG参数为DBMS_REDEFINITION.CONS_USE_ROWID。
如果源表有主键,可以不指定(默认为DBMS_REDEFINITION.CONS_USE_PK)。
DBMS_REDEFINITION.CAN_REDEF_TABLE('SYSDBA', 'TEST',OPTIONS_FLAG=>DBMS_REDEFINITION.CONS_USE_ROWID);
如果源表没有主键,不指定OPTIONS_FLAG参数执行CAN_REDEF_TABLE时会报“-20001: 不能联机重新定义无主键的表”的错误。
错误如下:

此时,将OPTIONS_FLAG参数指定为DBMS_REDEFINITION.CONS_USE_ROWID即可。
2、启动在线重做定义(必选)
执行START_REDEF_TABLE启动在线重定义:
DBMS_REDEFINITION.START_REDEF_TABLE('SYSDBA', 'TEST', 'TEST_TMP',OPTIONS_FLAG=>DBMS_REDEFINITION.CONS_USE_ROWID);
如果源表和目标表的列名不同,可以指定COL_MAPPING参数设置列的映射关系,如:
COL_MAPPING=> 'column1 as column2, col2 as col2'
执行该过程后,系统会自动在源表TEST上创建物化视图和物化视图日志。
select * from USER_MVIEWS;

3、查询重定义表信息(可选)
启动重定义表后,结束重定义之前,可以查询相关系统数据字典获取重定义表及操作信息。
select * from DBA_REDEFINITION_STATUS;select * from DBA_REDEFINITION_OBJECTS;

4、复制源表索引、约束等(可选)
重定义中,可使用 COPY_TABLE_DEPENDENTS 将原表上索引、约束、触发器等复制到新表(也可自己手动创建)。
注意:NUM_ERRORS是输出参数,表示出错个数,这里定义变量接受此参数,并打印参数值。
declaren_err INT;BEGINDBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('SYSDBA','TEST','TEST_TMP', NUM_ERRORS=>n_err);dbms_output.put_line('there has '||n_err|| ' errors');END;

5、重定义过程中可手动数据同步(可选)。
执行如下过程可手动数据同步,使用该过程可阶段性地完成部分数据同步。
DBMS_REDEFINITION.SYNC_INTERIM_TABLE('SYSDBA', 'TEST', 'TEST_TMP');

在重定义时,源表的数据仍然可以正常操作,比如修改、删除数据。
6、结束在线重定义(必选)
调用FINISH_REDEF_TABLE结束在线重定义:
DBMS_REDEFINITION.FINISH_REDEF_TABLE('SYSDBA', 'TEST', 'TEST_TMP');

此步骤结束后,查看TEST表结构可以看到TEST表已经更新为目标表结构:
select dbms_metadata.get_ddl('TABLE','TEST','SYSDBA');

之前系统创建的物化视图及物化视图日志也被自动删除。
SQL> select * from USER_MVIEWS;未选定行
查看在线重定义信息
调用START_REDEF_TABLE开始在线重定义过程后,查询DBA_REDEFINITION或SYSREDEF开头的相关数据字典表可以获取正在进行的在线重定义表对象及操作状态。
select * from DBA_REDEFINITION_STATUS;select * from DBA_REDEFINITION_OBJECTS;

终止和清除在线重定义
使用ABORT_REDEF_TABLE可以终止重定义;
使用DELETE_REDUNDANT_RECORD可以删除某些特定情况产生的系统表冗余记录。具体可以参考《DM8系统包使用手册》。
①使用DBMS_REDEFINITION在线重定义表,不仅可以更改表的定义,也可以更改表的存储(表空间),列的定义(重定义时指定列的映射),表的分区方式(如分区表修改为非分区表,非分区表修改为分区表)等。
②对于不存在主键或是伪主键( UNIQUE 约束列具有 NOT NULL约束)的表,不允许使用CONS_USE_PK 方式进行重定义,可指定使用CONS_USE_ROWID方式。
③在线重定义应预留足够的表空间(该表大小双倍空间),在业务空间期操作。
以上为本期分享,希望能带给大家帮助。想要了解更多往期干货,可访问页面最下方#达梦技术干货攻略#合集或下方相关分享。在此邀请更多学员参与“达梦技术干货投稿活动”,稿件获选后将在达梦“干货分享”专栏进行发布,欢迎来稿!
【干货攻略】如何使用 DBMS_SQLTUNE 包获取 SQL 执行信息





