将一个非分区表转换为分区表

/*
功能:
    将一个非分区表转换为分区表
基本思路:
    SST_DAY_TOTAL是(数据量上百万条,列比较多)一个非分区表,此时创建一个与SST_DAY_TOTAL同结构的分区表zhaozhenlong_partition,维护数据,
删除SST_DAY_TOTAL表,将zhaozhenlong_partition更名为SST_DAY_TOTA,删除zhaozhenlong_partition
*/
--具体步骤:
--1、查询非分区表数据
select to_char(rpt_date, 'yyyymm'), count(*) from SST_DAY_TOTAL group by to_char(rpt_date, 'yyyymm') order by to_char(RPT_DATE, 'yyyymm');

--2、创建分区表(结构和非分区表SST_DAY_TOTAL相同)
create table zhaozhenlong_partition
(
  GAS_ID                 VARCHAR2(12) not null,
  RPT_DATE               DATE not null,
  INV_NO                 VARCHAR2(12),
  ......
)
tablespace sdlg 
partition by range(rpt_date)(
partition rest values less than (maxvalue))

--3、交换数据(数据从非分区表到分区表)
alter table zhaozhenlong_partition exchange partition rest with table SST_DAY_TOTAL;

--4、查询分区表数据
select to_char(RPT_DATE, 'mm-yyyy'), count(*) from SST_DAY_TOTAL group by to_char(RPT_DATE, 'mm-yyyy');

--辅助脚本
/*
          select 'alter table zhaozhenlong_partition split partition rest at (to_date(''' 
                 || to_char(RPT_DATE, 'yyyymm') ||''',''yyyymm'')) into (partition p' 
                 || to_char(RPT_DATE, 'yyyymm')
                 || ', partition rest);'
          from zhaozhenlong_partition 
          group by to_char(RPT_DATE, 'yyyymm') 
          order by to_char(RPT_DATE, 'yyyymm')
*/

--5、对rest分区进行拆分
alter table zhaozhenlong_partition split partition rest at (to_date('200608','yyyymm')) into (partition p200608, partition rest);
alter table zhaozhenlong_partition split partition rest at (to_date('200609','yyyymm')) into (partition p200609, partition rest);
alter table zhaozhenlong_partition split partition rest at (to_date('200610','yyyymm')) into (partition p200610, partition rest);
alter table zhaozhenlong_partition split partition rest at (to_date('200611','yyyymm')) into (partition p200611, partition rest);
alter table zhaozhenlong_partition split partition rest at (to_date('200612','yyyymm')) into (partition p200612, partition rest);


--6、删除非分区表
drop table SST_DAY_TOTAL

--7、将分区表重命名为原非分区表名
alter table zhaozhenlong_partition rename to SST_DAY_TOTAL 

--8、删除中间处理过程的分区表
drop table zhaozhenlong_partition

 

________________________________


--补充
如果已存在分区表,要将某未分区表(与已分区表结构完全相同)加入到分区中:

alter table SST_DAY_TOTAL exchange partition p200608 with table zhaozhenlong_1;
alter table SST_DAY_TOTAL exchange partition p200609 with table zhaozhenlong_2;

如果zhaozhenlong_2不符合分区规则,则会报错,则需要指定without validation 来禁止检查
alter table SST_DAY_TOTAL exchange partition p200609 with table zhaozhenlong_2 without validation;


当然,如果你确认zhaozhenlong_1表中的数据是符合分区规则的,那指定without validation 之后,不会对zhaozhenlong_1进行全表扫描,
则会缩短exchange时间


REDEFINITION在线重定义表


7*24的业务运营系统中,对一个表进行在线重定义将是很棘手的事,因为业务实时的在对这个表进行进行插入,删除修改等操作,那么是否可以在线重定义表 呢,Oracle9i提供了在线重定义表包(DBMS_REDEFINITION),在修改表结构的同时可以进行DML操作。

1.构造原始数据表
SQL> create table red_test   --原始表,需要对这个表进行在线重定义
  2  as
  3  select  te_seq.nextval as id ,t.owner,t.object_name,10 as tvalue from dba_objects t ;
Table created

SQL> alter table RED_TEST --增加主键
  2    add constraint pri_redtest primary key (id);
Table altered

SQL> create index idc_retest_owner on red_test(owner) ;
Index created

需求:把red_test进行在线重定义,把tvuale字段更改为sal字段,并且sal=tvalue*10

2.验证是否可以在线重定义
SQL> EXEC Dbms_Redefinition.Can_Redef_Table('etl', 'red_test',DBMS_REDEFINITION.CONS_USE_PK);
PL/SQL procedure successfully completed

3.建立中间表
SQL> CREATE TABLE RED_TEST_MIDDLE AS  
  2  SELECT id,owner,object_name,tvalue as sal FROM red_test WHERE 1=2;
Table created

SQL> alter table RED_TEST_MIDDLE
  2    add constraint pri_redtest123 primary key (id);
Table altered

4.进行在线重定义
SQL> EXEC Dbms_Redefinition.Start_Redef_Table( 'ETL','RED_TEST','RED_TEST_MIDDLE','ID
ID, OWNER OWNER, OBJECT_NAME OBJECT_NAME,TVALUE*10 SAL');

PL/SQL procedure successfully completed

6.同步中间表,主要是同步重定义过程中变化的数据
SQL> EXEC dbms_redefinition.sync_interim_table('ETL', 'RED_TEST', 'RED_TEST_MIDDLE');

PL/SQL procedure successfully completed

7.测试在原始表继续插入是否还会同步
SQL> insert into RED_TEST select  te_seq.nextval as id ,t.owner,t.object_name,999 from dba_objects t ;
34193 rows inserted

SQL> commit;
Commit complete
--重定义过程原始表发生dml的数据会保留MV log,这就是为什么原始表要有主键的原因,当然也可以利用rowid
SQL> select count(*) from Mlog$_red_test;--原始产生的dml操作会记录在mv log

  COUNT(*)
----------
     34193

8.完成重定义
SQL> EXEC Dbms_Redefinition.Finish_Redef_Table( 'ETL', 'RED_TEST', 'RED_TEST_MIDDLE');
PL/SQL procedure successfully completed

9.检查是否完成了重定义
SQL> select ix.table_name,ix.index_name from user_indexes ix where ix.table_name='RED_TEST';

TABLE_NAME                     INDEX_NAME
------------------------------ ------------------------------
RED_TEST                       PRI_REDTEST123

SQL> select ix.table_name,ix.index_name from user_indexes ix where ix.table_name='RED_TEST_MIDDLE' ;

TABLE_NAME                     INDEX_NAME
------------------------------ ------------------------------
RED_TEST_MIDDLE                IDC_RETEST_OWNER
RED_TEST_MIDDLE                PRI_REDTEST

--比较一下中间表和原始表的索引,发觉仅仅是同步了数据,索引并不能同步过去,所以在正式环境中,应该先建立索引在完成重定义,建立索引可以放在第5步来做

10.删除中间表
SQL> drop table RED_TEST_MIDDLE ;

Table dropped
------------------------------------------------------------------------------------

一般会有这个需求,需要将在线大表(5G以上)更改为分区表,Dbms_Redefinition在线重定义非常慢,可能需要好几个小时,大表又是实时的 业务操作,这就存在很大的失败风险。有朋友曾经在线重定义过程中失败导致业务瘫痪,建议还是少用,或是不用,知道有这么回事就可以了。

个人觉得如下步骤比较保险,但是需要停机
a) export the table
b) create a new empty table that has the partition definition on it
c) import the table with IGNORE=Y

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/660456/viewspace-429539/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/660456/viewspace-429539/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值