ORACLE表的在线重定义

来源:互联网 发布:天津海量大数据 编辑:程序博客网 时间:2024/05/17 23:23
一、在线表重定义的用处:
1、修改表或者簇的存储参数
2、在相同schema的表空间之间,可以移动表或簇
注意:如果表的可以停止dml操作,则可以利用alter table move来进行表空间的更改
3、增加、修改或者删除一个或多个表或簇的列
4、非簇表可以做添加或删除分区的支持
5、改变分区的结构
6、更改简单表的分区物理属性,在相同schema的表空间之间,也可以将其分区更改表空间
7、更改物化视图日志或an Oracle Streams Advanced Queueing队列表的物理属性
8、添加支持并行查询
9、通过重建表或簇来减少碎片
注意:在很多cases里,可以通过在线段shrink的简单方法来减少碎片
10、转换堆组织表为索引组织表,反之亦可
11、一个关系表转换成有对象列的表,反之亦可
12、一个对象表转换成一个关系表或者有对象列的表,反之亦可
二、限制在线表的重定义
1、在sys和system schema下的表不能使用在线重定义
2、临时表不能
3、索引组织表的溢出表不能被独立的在线重定义
4、有bfile的列的表不能重新定义
5、表具有 fine-grained access control (row-level security)不能被在线重定义
6、表有long列,要将其转换成clobs,long raw列转换成blobs可以做在线重定义,lob列也可作
7、表的重定义不能做nologging
8、具有物化视图日志的表不能做在线重定义
9、可以利用cast操作来做数组到嵌套表的列映射。反之则不行
10、其他的一些信息你可以参考官方文档
三、在线表的重定义有两种方法:OEM里的Reorganize Objects wizard或利用DBMS_REDEFINITION包.
介绍后一种方法,因为后一种会了,前一种肯定会了
method1:Performing Online Redefinition with DBMS_REDEFINITION的大概步骤介绍:
1、选择by key或者by rowid来做重定义。
by key:利用主键或者伪主键来进行重定义,伪主键就是具有not null约束组件的所有字段唯一键。重定义前后表版本应该
有相同的主键列。这个是首选和默认的重定义方法。
by rowid:如果没有键是可用的那么就用by rowid。用by rowid,就会有一个名为M_ROW$$的隐含列添加到重定义后表里。如果在重定义完之后,最好把M_ROW$$列给删除或者标记无效。在索引组织表上不能用这种方法。
如果利用by rowid来做重定义,compatible参数在10.1或者更早版本,就要利用ALTER TABLE table_name SET UNUSED (M_ROW$$);来设置;但是compatible参数在10.2或者更新的版本,会自动设置unused。
2、通过执行CAN_REDEF_TABLE存储过程来验证表能被在线重定义。如果table被验证不能被在线重新定义,那么这个存储过程会提示为什么不能被在线重新定义的出错。
DBMS_REDEFINITION.CAN_REDEF_TABLE (   uname         IN  VARCHAR2,   tname        IN  VARCHAR2,   options_flag  IN  PLS_INTEGER := 1,   part_name     IN  VARCHAR2 := NULL);
3、创建一个具有原始表全部的逻辑和物理属性的中间表(在相同对象里表被重新定义)。如果列需要删除,在定义中间表时不要包含该列。如果一列被添加,那在定义中间表时添加该列。如果有列要被修改,那在定义中间表时定义你你需要的属性。
4、如果在重定义大表,可以通过运行下面的语句开启并行度来提高性能:
alter session force parallel dml parallel degree-of-parallelism;alter session force parallel query parallel degree-of-parallelism;
5、调用start_redef_table来进行重定义处理,这个存储过程有一些参数:
DBMS_REDEFINITION.START_REDEF_TABLE (   uname          IN VARCHAR2,-->被重定义表的schema   orig_table     IN VARCHAR2,-->被重定义表的表名   int_table      IN VARCHAR2,-->中间表名   col_mapping    IN VARCHAR2 := NULL,-->重定义后所有的列名,默认是null即和原始表一样的所有列的列名,具体对这个列的解释可以参考官方文档   options_flag   IN BINARY_INTEGER := 1,-->重定义的方法(by key or by rowid)   orderby_cols   IN VARCHAR2 := NULL,-->可选操作,被用来排序行的列   part_name     IN  VARCHAR2 := NULL);-->如果重定义一个分区表某个分区时,指定的分区名
注意:这个过程是复制数据,可能会花费一段时间。在这个表被定义的过程整个过程里,查询和dml语句是可以进行的。
如果执行这个存储过程到中途失败,必须要调abort_redef_table,否则再次尝试重定义也会失败。
6、从被定义的表复制相关联的对象(如:triggers、indexes、grants、constraints)和统计信息到中间表,有两种可选方法。
方法一:利用copy_table_dependents,是个更自动的过程,但同时可以复制统计信息,这个存储过程全部执行完后,相关联的对象和被定义的表的相关对象名是一样的。
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(   uname                    IN  VARCHAR2,-->被重定义表的schema   orig_table               IN  VARCHAR2,-->被重定义表的表名   int_table                IN  VARCHAR2,-->中间表名   copy_indexes             IN  PLS_INTEGER := 1,-->复制索引,默认值是1,利用dbms_redefinition.cons_orig_params来复制指定索引   copy_triggers            IN  BOOLEAN     := TRUE,-->复制触发器   copy_constraints         IN  BOOLEAN     := TRUE,-->复制约束   copy_privileges          IN  BOOLEAN     := TRUE,-->复制权限   ignore_errors            IN  BOOLEAN     := FALSE,-->true,出错报出,但继续执行;false出错报出,会停止执行   num_errors               OUT PLS_INTEGER,-->在复制时报错的数据   copy_statistics          IN  BOOLEAN     := FALSE); -->是否copy统计信息,默认是不copy的。
注:如果执行有错误,可以查询dba_redefinition_errors试图,然后解决问题,重新执行失败的对象,已成功的,不需再次处理。
方法二:可以手工建立相关联对象。在9i版本里有些时候还需要用到手工去建立相关联对象。
如果是手工建立相关联对象的话,建立完成后要执行REGISTER_DEPENDENT_OBJECT,让其相关联对象在重定义过后恢复到重定义之前之前。如果针对方法一失败后,可以再利用方法二处理,然后再注册对象。可以在DBA_REDEFINITION_OBJECTS查找相关信息。
The UNREGISTER_DEPENDENT_OBJECT procedure can be used to unregister a dependent object on the table being redefined and on the interim table.
7、执行finish_redef_table存储过程来完成表的重定义。在执行期间,被定义的原始表在很短的时间里被锁在独占模式,有大量独立数据在原始表里。
DBMS_REDEFINITION.FINISH_REDEF_TABLE (   uname       IN VARCHAR2,   orig_table  IN VARCHAR2,   int_table   IN VARCHAR2,   part_name   IN  VARCHAR2 := NULL);默认是空值,如果是某个分区,一定要指定分区名
三、在重定义时遇到的问题及解决思路
1、执行中间同步:
在开始了start_redef_table之后并且执行finish_redef_table之前,在这个过程中,如果有大量的DML语句在原始表上操作,我们可以周期性做原始表和中间表的同步工作。这个方法就是用sync_interim_table存储过程。这样做的好处可以缩短finish_redef_table处理的时间。在做sync_interim_table时,不限制其次数。
The small amount of time that the original table is locked during FINISH_REDEF_TABLE is independent of whether SYNC_INTERIM_TABLE has been called.
DBMS_REDEFINITION.SYNC_INTERIM_TABLE (   uname          IN  VARCHAR2,   orig_table     IN  VARCHAR2,   int_table      IN  VARCHAR2,   part_name      IN  VARCHAR2 := NULL);
2、中止在线表的重定义和解决错误。
在执行在线重定义过程中出现了错误或须你要通过调用abort_redef_table中断在线重定义的进程。这个存储过程就是删除临时日志和相关联在线重定义的表。这个过程被调用后,你能删除中间表和他的相关联对象。如果在线重定义过程须重启,如果你进行abort_redef_table,你重新定义也会失败
DBMS_REDEFINITION.ABORT_REDEF_TABLE (   uname       IN VARCHAR2,   orig_table  IN VARCHAR2,   int_table   IN VARCHAR2,  part_name    IN  VARCHAR2 := NULL);
四、针对分区表的特殊情况说明
只有在10gr2或者之后版本,可以在线重新定义一个分区表的分区,比如:在不影响dml的操作情况,可以变更某个分区的所在的表空间;你想移动整个分区表,可以一个一个移动分区来避免因资源的问题导致在move过程中产生的问题。
在线重定义分区表的单个分区与在线重定义一张表的去表
1、首先不需要复制相关联的对象,使用copy_table_dependents对单个分区操作时无效的。
2、 必须手工在中间表上创建局部索引。
3、在start_redef_table存储过程的列的映射col_mapping必须是null。
注:如果更改某个分区的表空间,如果可以停止dml操作,则可以用alter table move partition语句来操作。
在线重定义分区表的某个分区时,针对中间表的一些规则
1、如果重定义的分区是简单的hash、range、list分区,则中间表为非分区表
2、如果重定义的分区是range-hash复合分区表,则中间表必须是hash分区表。另外,中间表的分区键必须和原始表的子分区的键相同,同时中间表的分区数目必须和被重定义的范围分区的子分区的数目一样。
3、如果重定义的分区是range-list复合分区表,中间表是list分区。另外,间表的分区键必须和原始表的子分区的键相同,同时中间表列表分区的列表值必须和被重定义的范围分区的子列表分区的列表值一样
索引组织表的分区,则有下面的约束规则:
1、中间表必须也是索引组织表
2、原始表和中间表必须在相同的列和顺序有主键
3、如果key值压缩功能是enabled,则原始表和中间表都要enabled,并且要有相同prefix长度。
4、原始表和中间表都要有溢出段,或者两个都没有。针对映射表也是这样。
5、原始表和中间表在lob列上要有相同存储属性
五、执行dbms_redefintion的权限
execute_catalog_role,create any table,alter any table,drop any table,lock any table,select any table
如果要执行copy_table_dependents时需要create any trigger,create any index,亲,后面讲进行案例分析
0 0
原创粉丝点击