方法一:利用原表重建分区表
需要重建分区的表名为T_TEST,表有两列swglm和lr_sj。
CREATE TABLE t_test_new(swglm ,lr_sj ) PARTITION BY RANGE(lr_sj)
(PARTITION P20070101 VALUES LESS THAN (TIMESTAMP'2007-01-01 00:00:00'),
PARTITION P20080101 VALUES LESS THAN (TIMESTAMP'2008-01-01 00:00:00'),
PARTITION P20090101 VALUES LESS THAN (TIMESTAMP'2009-01-01 00:00:00'),
PARTITION P20100101 VALUES LESS THAN (TIMESTAMP'2010-01-01 00:00:00'),
PARTITION P20110101 VALUES LESS THAN (TIMESTAMP'2011-01-01 00:00:00'),
PARTITION PMAX VALUES LESS THAN (MAXVALUE))
AS SELECT swglm,lr_sj FROM t_test;
RENAME t_test TO t_test_old;
RENAME t_test_new TO t_test;
优点:方法简单易用,由于采用DDL语句,不会产生UNDO,且只产生少量REDO,效率相对较高,而且建表完成后数据已经在分布到各个分区中了。
不足:对于数据的一致性方面还需要额外的考虑。由于几乎没有办法通过手工锁定T表的方式保证一致性,在执行CREATE TABLE语句和RENAME t_test_new TO t_test语句直接的修改可能会丢失,如果要保证一致性,需要在执行完语句后对数据进行检查,而这个代价是比较大的。另外在执行两个RENAME语句之间执行的对T的访问会失败。
适用于修改不频繁的表,在闲时进行操作,表的数据量不宜太大。
方法二:使用交换分区的方法
需要重建分区的表名为T_TEST,表有两列swglm和lr_sj。
CREATE TABLE t_test_new(swglm NUMBER(15) PRIMARY KEY ,lr_sj TIMESTAMP(6)) PARTITION BY RANGE(lr_sj)
( PARTITION P20110101 VALUES LESS THAN (TIMESTAMP'2011-01-01 00:00:00'),
PARTITION PMAX VALUES LESS THAN (MAXVALUE));
ALTER TABLE T_TEST_NEW EXCHANGE PARTITION P20110101 WITH TABLE T_TEST;
RENAME t_test TO t_test_old;
RENAME t_test_new TO t_test;
优点:只是对数据字典中分区和表的定义进行了修改,没有数据的修改或复制,效率最高。如果对数据在分区中的分布没有进一步要求的话,实现比较简单。在执行完RENAME操作后,可以检查T_TEST_OLD中是否存在数据,如果存在的话,直接将这些数据插入到T_TEST中,可以保证对T_TEST插入的操作不会丢失。
不足:仍然存在一致性问题,交换分区之后RENAME T_TEST_NEW TO T_TEST之前,查询、更新和删除会出现错误或访问不到数据。如果要求数据分布到多个分区中,则需要进行分区的SPLIT操作,会增加操作的复杂度,效率也会降低。
注意:此方法只适用于包含大数据量的表转到分区表中的一个分区的操作。应尽量在闲时进行操作。 两表必须要有一样的主键。
方法三:在线重定义
需要重建分区的表名为T_TEST,表有两列swglm和lr_sj。
1.exec dbms_redefinition.can_redef_table(user,‘t_test’,dbms_redefinition.cons_use_pk) --验证表是否可以重定义
2.CREATE TABLE t_test_new(swglm NUMBER(15) PRIMARY KEY ,lr_sj TIMESTAMP(6)) PARTITION BY RANGE(lr_sj)
(PARTITION P20070101 VALUES LESS THAN (TIMESTAMP'2007-01-01 00:00:00'),
PARTITION P20080101 VALUES LESS THAN (TIMESTAMP'2008-01-01 00:00:00'),
PARTITION P20090101 VALUES LESS THAN (TIMESTAMP'2009-01-01 00:00:00'),
PARTITION P20100101 VALUES LESS THAN (TIMESTAMP'2010-01-01 00:00:00'),
PARTITION P20110101 VALUES LESS THAN (TIMESTAMP'2011-01-01 00:00:00'),
PARTITION PMAX VALUES LESS THAN (MAXVALUE)); --建立和原表表结构一样的分区表作为中间表
3.exec dbms_redefinition.start_redef_table(user,'t_test','t_test_new'); --执行表的在线重定义
4. execute dbms_redefinition.sync_interim_table(user,'t_test','t_test_new'); --执行把中间表的内容和数据与源表进行同步
5.exec dbms_redefinition.finish_redef_table(user,'t_test','t_test_new'); --执行结束在线定义过程
注:第一步可能报:ORA-12089: 不能联机重新定义无主键的表 "SYSLOGUSR"."T_TEST" , 这时需要为T_TEST添加主键.
第二步可能报:ORA-12091: 不能联机重新定义具有实体化视图的表 "SYSLOGUSR"."T_TEST"。
这时需要去除首次执行START_REDEF_TABLE 产生的快照日志.
SQL> select log_table from user_snapshot_logs;
LOG_TABLE
-------------------------
MLOG$_T_TEST
SQL> drop snapshot log on T_TEST;
Materialized view log dropped.
SQL> select TABLE_NAME , status from user_snapshots;
TABLE_NAME STATUS
------------------------------ -------
INT_T_TEST INVALID
SQL> select mview_name, compile_state from user_mviews;
MVIEW_NAME COMPILE_STATE
------------------------------ -------------------
INT_T_TEST ERROR
SQL> drop materialized view int_T_TEST;
Materialized view dropped.
即可继续.
优点:保证数据的一致性,在大部分时间内,表T_TEST都可以正常进行DML操作。只在切换的瞬间锁表,具有很高的可用性。这种方法具有很强的灵活性,对各种不同的需要都能满足。而且,可以在切换前进行相应的授权并建立各种约束,可以做到切换完成后不再需要任何额外的管理操作。
不足:实现上比上面两种略显复杂。
适用于各种情况。