上月通过在线重定义的方式对B2B库做了一次普通表转分区表的操作,涉及的表大小约为72G;听起来很玄乎,其实在线重定义的原理并不复杂:依据业务需求建立一张空的分区表(可以看成是中间表),接着将原表数据不断同步到中间表,同步完成后瞬间切换表名,中间表转正、原普通表离职。此方法的优点是可以保证业务的连续性,与此对应的代价是必须为中间表腾出足够的空间,例如在此案例中应准备至少72G的空间来迎接中间表,另外,别忘了索引。。。插播一句题外话,规划重于调整,尤其是对于大库,这一点尤为重要。

整个操作的具体步骤如下:

1. 加文件,准备足够的空间(包括数据表空间、索引表空间)

alter tablespace tbs_biz_scrab add datafile 'D:\U01\RWDATA\TBS_BIZ_SCRAB\TBS_BIZ_SCRAB13.DBF' size 8g autoextend off;
alter tablespace tbs_biz_scrab add datafile 'E:\U02\RWDATA\TBS_BIZ_SCRAB\TBS_BIZ_SCRAB14.DBF' size 8g autoextend off;
alter tablespace tbs_biz_scrab add datafile 'D:\U01\RWDATA\TBS_BIZ_SCRAB\TBS_BIZ_SCRAB15.DBF' size 8g autoextend off;
alter tablespace tbs_biz_scrab add datafile 'E:\U02\RWDATA\TBS_BIZ_SCRAB\TBS_BIZ_SCRAB16.DBF' size 8g autoextend off;
alter tablespace tbs_biz_scrab add datafile 'D:\U01\RWDATA\TBS_BIZ_SCRAB\TBS_BIZ_SCRAB17.DBF' size 8g autoextend off;
alter tablespace tbs_biz_scrab add datafile 'E:\U02\RWDATA\TBS_BIZ_SCRAB\TBS_BIZ_SCRAB18.DBF' size 8g autoextend off;
alter tablespace tbs_biz_scrab add datafile 'D:\U01\RWDATA\TBS_BIZ_SCRAB\TBS_BIZ_SCRAB19.DBF' size 8g autoextend off;
alter tablespace tbs_biz_scrab add datafile 'E:\U02\RWDATA\TBS_BIZ_SCRAB\TBS_BIZ_SCRAB20.DBF' size 8g autoextend off;

alter tablespace tbs_index2 add datafile 'D:\U01\RWDATA\TBS_INDEX2\TBS_INDEX203.DBF' size 4g autoextend off;
alter tablespace tbs_index2 add datafile 'E:\U02\RWDATA\TBS_INDEX2\TBS_INDEX204.DBF' size 4g autoextend off;
alter tablespace tbs_index2 add datafile 'D:\U01\RWDATA\TBS_INDEX2\TBS_INDEX205.DBF' size 4g autoextend off;
alter tablespace tbs_index2 add datafile 'E:\U02\RWDATA\TBS_INDEX2\TBS_INDEX206.DBF' size 4g autoextend off;
alter tablespace tbs_index2 add datafile 'D:\U01\RWDATA\TBS_INDEX2\TBS_INDEX207.DBF' size 4g autoextend off;
alter tablespace tbs_index2 add datafile 'E:\U02\RWDATA\TBS_INDEX2\TBS_INDEX208.DBF' size 4g autoextend off;

2. 使用数据泵导出备份b2b_scrabdata表(谨慎。。。以防不测-_-||)

expdp b2b/******* DIRECTORY=B2B_DUMP DUMPFILE=20091016_b2b_scrabdata.dmp TABLES=b2b_scrabdata PARALLEL=1 LOGFILE=20091016_b2b_scrabdata.log;

3. 依据原表及业务需求建立中间表

CREATE TABLE temp_scrabdata PARTITION BY RANGE (scrabid)
(PARTITION P001 VALUES LESS THAN (501) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P002 VALUES LESS THAN (1001) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P003 VALUES LESS THAN (1501) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P004 VALUES LESS THAN (2001) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P005 VALUES LESS THAN (2501) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P006 VALUES LESS THAN (3001) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P007 VALUES LESS THAN (3501) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P008 VALUES LESS THAN (4001) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P009 VALUES LESS THAN (4501) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P010 VALUES LESS THAN (5001) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P011 VALUES LESS THAN (5501) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P012 VALUES LESS THAN (6001) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P013 VALUES LESS THAN (6501) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P014 VALUES LESS THAN (7001) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P015 VALUES LESS THAN (7501) TABLESPACE TBS_BIZ_SCRAB,
PARTITION P016 VALUES LESS THAN (MAXVALUE) TABLESPACE TBS_BIZ_SCRAB)
AS SELECT * FROM b2b_scrabdata where 1=0;

建立中间表主键(注:主键和索引名在转换之后并不会切换,转换后的分区表将使用中间表的主键和索引名)

alter table temp_scrabdata
add constraint PK_NEW_SCRABDATA primary key (SCRABDATAID)
using index
tablespace tbs_index2;

建立中间表索引

create index IDX_NEW_SCRABDATA_SCRABID on temp_scrabdata(scrabid, scrabdataid) local tablespace tbs_index2;
create index IDX_NEW_SCRABDATA_SCRABIDNAME on temp_scrabdata(scrabid, bizname) local tablespace tbs_index2;
create index IDX_NEW_SCRABDATA_SCRABIDWEB on temp_scrabdata(scrabid, web_id) local tablespace tbs_index2;
create index IDX_NEW_SCRABDATA_NAME on temp_scrabdata(bizname) global tablespace tbs_index2;

4. 执行转换

验证原表主键是否完整

SQL> EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE('B2B', 'B2B_SCRABDATA', DBMS_REDEFINITION.CONS_USE_PK);

PL/SQL 过程已成功完成。

确认转换前的表信息

select * from user_tab_partitions where table_name='TEMP_SCRABDATA';
select * from user_tab_partitions where table_name='B2B_SCRABDATA';

执行转换

SQL> exec dbms_redefinition.start_redef_table('B2B','B2B_SCRABDATA','TEMP_SCRABDATA');

PL/SQL 过程已成功完成。

结束转换完成同步

SQL> exec dbms_redefinition.finish_redef_table('B2B','B2B_SCRABDATA','TEMP_SCRABDATA');

PL/SQL 过程已成功完成。

确认转换后的表信息

select * from user_tab_partitions where table_name='TEMP_SCRABDATA';
select * from user_tab_partitions where table_name='B2B_SCRABDATA';

5. 补充:如何split分区

执行split

alter table part_scrabdata
split partition P016 at(8001)
into (partition P016 TABLESPACE TBS_PART, partition P017 TABLESPACE TBS_PART)
update indexes; --避免索引失效

确认split后的索引状态

select index_name,partition_name,status from user_ind_partitions;
select index_name, status from user_indexes where index_name='PK_TEMP_SCRABDATA';
select constraint_name, status from user_constraints where index_name='PK_TEMP_SCRABDATA';

(注:建议提前预估数据量增长曲线,尽量在MAXVALUE分区有新数据之前完成split,以降低开销)

Rand Posts:



我们在天上的父
愿人都尊你的名为圣
愿你的国降临
愿你的旨意行在地上如同行在天上
我们将顺着你的指引前行
直至重归你的梯下


4 条评论



  1. 72G……存了上亿条了?

    [ 引用 ]


  2. Paul 在 2009年11月17日 23:00 说到:

    72G……存了上亿条了?

    恩,最近几个月数据抓得比较猛。。。不分的话,整理的那个存过有点撑不住了。。。转换大概跑了4小时,不过当时无并发

    [ 引用 ]


  3. 冬至啦,小小来送饺子啦 :)

    [ 引用 ]


  4. 小小 在 2009年12月22日 21:15 说到:

    冬至啦,小小来送饺子啦 :)

    跪谢师傅,哈哈 :o

    [ 引用 ]

发表评论

文明上网,共建和谐社会。