如何将一个普通的非分区表进行分区4 DBMS_REDEFINITION

来源:这里教程网 时间:2026-03-03 21:42:54 作者:

如何将一个普通的非分区表进行分区4 DBMS_REDEFINITION ## 参考文档: Case Study for a Large Non+Partition Table to a Partition Table with Online Transactions Occuring How To Partition Existing Table Using DBMS_REDEFINITION (Doc ID 472449.1) How To Change the Partition Column Of A Partitioned Table Using DBMS_Redefinition (Doc ID 846405.1) ## 简介: 本次演示DBMS_REDEFINITION在线重定义分区表的几个步骤: 1:建立一个需要被重定义的表A(非分区) 2:建立一个中间表B(分区表) 3:用表B结构来重定义表A,使A表分区 执行在线重定义所需要权限:     角色:EXECUTE_CATALOG_ROLE     权限:CREATE ANY TABLE、ALTER ANY TABLE、DROP ANY TABLE、LOCK ANY TABLE、SELECT ANY TABLE ## 1、创建模拟环境 创建用户 create user PARTION identified by partion; grant dba to partion; connect partion/partion 创建一个表 CREATE TABLE unpar_table ( a NUMBER, y number, name VARCHAR2(100), date_used date); 为表添加主键 alter table unpar_table ADD (CONSTRAINT unpar_table_pk PRIMARY KEY (a,y)); 在表中插入数据 ++ load table with 1,000,000 rows begin for i in 1 .. 1000 loop for j in 1 .. 1000 loop insert into unpar_table values ( i, j, dbms_random.random, sysdate+j ); end loop; end loop; end; / commit; +++++++++++++++++++++++++++++++++++++++++++++++++ 收集统计信息,并查看表的行数 EXEC DBMS_STATS.gather_table_stats('partion', 'unpar_table', cascade => TRUE); SELECT num_rows FROM user_tables WHERE table_name = 'UNPAR_TABLE'; ## 2、创建分区临时表 CREATE TABLE par_table ( a NUMBER, y number, name VARCHAR2(100),date_used DATE) PARTITION BY RANGE (date_used) (PARTITION unpar_table_12 VALUES LESS THAN (TO_DATE('10/05/2015', 'DD/MM/YYYY')), PARTITION unpar_table_15 VALUES LESS THAN (TO_DATE('15/05/2015', 'DD/MM/YYYY')), PARTITION unpar_table_MX VALUES LESS THAN (MAXVALUE)); ++++++++++++++++++++++++++++++++++++++++++++++++++ ## 3、dbms_redefinition在线重定义 检查是否可以重定义表 EXEC Dbms_Redefinition.can_redef_table('partion', 'unpar_table'); 执行在线同步 BEGIN DBMS_REDEFINITION.start_redef_table( uname => 'partion', orig_table => 'unpar_table', int_table => 'par_table'); END; / 查询相关视图 select mview_name,container_name, build_mode from user_mviews; MVIEW_NAME CONTAINER_NAME BUILD_MOD ++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ +++++++++ PAR_TABLE PAR_TABLE PREBUILT 在线同步过程中,往表中插入数据 SQL> begin for i in 2000 .. 2010 loop for j in 2000 .. 2100 loop insert into unpar_table values ( i, j, dbms_random.random, sysdate+j ); end loop; end loop; end; / commit; 查询数据是否插入 SQL> select count(*) from MLOG$_UNPAR_TABLE;   COUNT(*) ++++++++++       1000 如果在执行完成DBMS_REDEFINITION.START_REDEF_TABLE过程后,立即执行DBMS_REDEFINITION.FINISH_REDEF_TABLE 过程, 这会导致在重定义表上执行了大量的DML操作,那么可以选择执行一次或多次的DBMS_REDEFINITION.SYNC_INTERIM_TABLE过程, 以减少最后一步执行FINISH_REDEF_TABLE过程时的锁定时间    SQL> BEGIN dbms_redefinition.sync_interim_table( uname => 'partion', orig_table => 'unpar_table', int_table => 'par_table'); END; ALTER TABLE par_table ADD (CONSTRAINT par_table_pk2 PRIMARY KEY (a,y));  EXEC DBMS_STATS.gather_table_stats('partion', 'par_table', cascade => TRUE); ##  4、完成表的重定义。  这个过程中,原始表会被独占模式锁定一小段时间,具体时间和表的数据量有关 BEGIN dbms_redefinition.finish_redef_table( uname => 'partion', orig_table => 'unpar_table', int_table => 'par_table'); END; / select count(*) from par_table ;   COUNT(*) ++++++++++    1001000         select count(*) from unpar_table ;   COUNT(*) ++++++++++    1001000 ##  5、查询原表是否成为分区方式 SELECT partitioned FROM user_tables WHERE table_name = 'UNPAR_TABLE'; PAR +++ YES SQL> SELECT partitioned FROM user_tables WHERE table_name = 'PAR_TABLE'; PAR --- NO SELECT partition_name, num_rows FROM user_tab_partitions WHERE table_name = 'UNPAR_TABLE'; PARTITION_NAME NUM_ROWS ++++++++++++++++++++++++++++++ ++++++++++ UNPAR_TABLE_12 169000 UNPAR_TABLE_15 5000 UNPAR_TABLE_MX 827000 drop TABLE par_table cascade constraints; ## 6.约束之类的药过去可以通过下面的步骤,索引建议自己再新建索引 DECLARE num_errors PLS_INTEGER; BEGIN DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('USERPC', 'TRX_BASE', 'TRX_BASE_TMP',DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE, num_errors); END; / ## 7.正常来说是无法通过在线重定义修改表的类型的,但是 number 转varchar 可以通过下面的办法  参考文档: ORA-42016: Shape Of Interim Table Does Not Match Specified Column Mapping (Doc ID 2016240.1) https://www.itpub.net/forum.php?mod=viewthread&page=2&tid=1280805 SQL>  create table  UAS_USER ( USER_ID     number,   USER_NO      VARCHAR2(256),   USERNAME     VARCHAR2(256),   PASSWORD     VARCHAR2(256),   MODIFY_TIME  DATE not null,   MODIFY_ADMIN VARCHAR2(64) );  2    3    4    5    6    7    8    9   Table created. SQL>  alter table UAS_USER   add constraint PK_UAS_USER primary key (USER_ID);   2   Table altered. SQL> insert into UAS_USER values ( 1,'1','zc','zc',sysdate,'zc'); 1 row created. SQL> insert into UAS_USER values ( 2,'1','zc','zc',sysdate,'zc'); 1 row created. SQL> commit; Commit complete. SQL> commit; Commit complete. SQL> create table INTER_UAS_USER ( USER_ID      varchar2(20) not null,   USER_NO      VARCHAR2(256),   USERNAME     VARCHAR2(256),   PASSWORD     VARCHAR2(256),   MODIFY_TIME  DATE not null,   MODIFY_ADMIN VARCHAR2(64) );   2    3    4    5    6    7    8    9   Table created. SQL> alter table INTER_UAS_USER   add constraint PK_INTER_UAS_USER primary key (USER_ID);  2   Table altered.   SQL> exec dbms_redefinition.can_redef_table('ZC','UAS_USER'); PL/SQL procedure successfully completed. SQL> exec dbms_redefinition.start_redef_table('ZC','UAS_USER','INTER_UAS_USER', 'to_char(USER_ID) USER_ID, USER_NO USER_NO, USERNAME USERNAME, PASSWORD PASSWORD, MODIFY_TIME MODIFY_TIME, MODIFY_ADMIN MODIFY_ADMIN', dbms_redefinition.cons_use_rowid); PL/SQL procedure successfully completed. SQL> exec dbms_redefinition.sync_interim_table('ZC','UAS_USER','INTER_UAS_USER'); PL/SQL procedure successfully completed. SQL>  SQL> exec dbms_redefinition.finish_redef_table('ZC','UAS_USER','INTER_UAS_USER'); PL/SQL procedure successfully completed. SQL> desc uas_user;  Name    Null?    Type  ----------------------------------------- -------- ----------------------------  USER_ID    NOT NULL VARCHAR2(20)  USER_NO     VARCHAR2(256)  USERNAME     VARCHAR2(256)  PASSWORD     VARCHAR2(256)  MODIFY_TIME    NOT NULL DATE  MODIFY_ADMIN     VARCHAR2(64)

相关推荐