Oracle普通表基于Rowid在线重定义表分区

公司的一张数据表数据量太大,为提高数据查询速度,对其进行在线重定义分区,网上查阅各路大神帖子,自我实验总结如下:
测试数据为一张4亿+多条数据量源表:TAB_SJ_SIGNAL_VALUE_61 ;
特点:表数据根据列 TIME 有明显的时间划分;

1--建中间表t3,手动创建分区,下面操作都是默认使用的中间表t3;
create table t3 partition by range(time)  --创建中间表t3,按时间time分区;
 (partition a1 values less than (to_date('2016/01/26','yyyy/mm/dd')) tablespace db_sj_61_v1, --分区a1
 partition a2 values less than (to_date('2016/01/27','yyyy/mm/dd')) tablespace db_sj_61_v1, --分区a2
 partition a3 values less than (to_date('2016/01/28','yyyy/mm/dd')) tablespace db_sj_61_v1,
 partition a4 values less than (to_date('2016/01/29','yyyy/mm/dd')) tablespace db_sj_61_v1,
 partition a5 values less than (maxvalue) tablespace db_sj_61_v1;
 as select * from TAB_SJ_SIGNAL_VALUE_61 where 1=2;  --表结构可以根据已有源表来直接引用;
其他说明:
  1)分区a1,时间范围是小于2016/01/26的所有数据,使用的表空间db_sj_61_v1;
  2)分区a2,存储的是26号全天数据,我这里使用了与a1同一个表空间,每个分区可以使用不同的表空间,读者可根据自己的实际情况决定;
  3)分区a5,对于大于某个范围后的所有值,可以使用函数 maxvalue 来确定分区;

2--创建多通道,提高执行效率;
alter session force parallel dml parallel 8;
alter session force parallel query parallel 8;
alter session force parallel ddl parallel 4;

3--验证是否可行
begin 
  dbms_redefinition. can_redef_table('ADMIN1','TAB_SJ_SIGNAL_VALUE_61',dbms_redefinition.cons_use_rowid);
 end;
说明: dbms_redefinition. can_redef_table ('用户名','源表',重定义方式(主键或Rowid))

4--执行重定义操作
begin 
  dbms_redefinition. start_redef_table('ADMIN1','TAB_SJ_SIGNAL_VALUE_61','t3',null,dbms_redefinition.cons_use_rowid);
end;
说明:dbms_redefinition. start_redef_table ('用户名','源表','中间表',映射关系(可选),方式(主键或Rowid) );

5--迁移关联数据,如索引、触发器等等
declare
 num_errors pls_integer;
begin
  dbms_redefinition.copy_table_dependent
  (uname => 'ADMIN1',
  orig_table  => 'TAB_SJ_SIGNAL_VALUE_61',
  int_table   => 't3',
  copy_indexes    => 0,
  copy_triggers    => TRUE,
  copy_constraints => FALSE,
  copy_privileges  => TRUE,
  ignore_errors    => FALSE,
  num_errors       => num_errors,
  copy_statistics  => FALSE);
END;

6--执行数据同步
begin
  dbms_redefinition. sync_interim_table('ADMIN1','TAB_SJ_SIGNAL_VALUE_61','T3');
end;

7--完成重定义
begin
  dbms_redefinition. finish_redef_table('ADMIN1','TAB_SJ_SIGNAL_VALUE_61','T3');
end;

*1--Oracle11g开始提供了自动创建分区的功能;
create table t4 partition by range(time)   --仍然以时间为划分节点
interval(numtodsinterval (1,'hour'))   --时间间隔设置为1小时
store in (db_sj_61_v2)  --设置存储表空间db_sj_61_v2
(partition p0 valuse less than(to_date('2016/01/25 00:00:00','yyyy/mm/dd hh24:mi:ss')))  --初始分区p0
as select * from TAB_SJ_SIGNAL_VALUE_61 where 1=2; 
详细说明:
  1)在做完实验后,发现按天划分每个分区里的数据量依然很大,遂决定按小时进行自动分区,其他步骤都一样;
  2)注意函数numtodsinterval作用的范围是:second to day 秒级-天级别(eg:second/minute/hour/day);
    与numtodsinterval函数类似numtoyminterval,作用范围为year to month年-月级别数据(eg:month/year);
  3)store in (tbs1,tbs2,...)这里可以设置多个存储的表空间,以逗号隔开即可;
  4)初始分区p0,设置存放初始时间之前的所有数据,后面时间的分区交给系统自动创建;

***************************
--查询重定义后的结果,可分别查询源表与中间表,数据有问题时甚至可以通过改名互换解决;
SQL> select partition_name,high_value,tablespace_name
  2  from user_tab_partitions where table_name='TAB_SJ_SIGNAL_VALUE_61'
  3  order by partition_position;

--检查重定义后索引信息的存在与否
SQL> select index_name,index_type,table_owner,table_name 
2 from user_indexes where table_name = 'TAB_SJ_SIGNAL_VALUE_61'; 

猜你喜欢

转载自blog.csdn.net/karloo/article/details/51841516