Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1119614
  • 博文数量: 231
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 2662
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-03 16:35
个人简介

学无止境

文章分类

全部博文(231)

文章存档

2014年(7)

2013年(103)

2011年(11)

2010年(53)

2009年(57)

分类: Oracle

2010-09-03 19:58:48

主要使用dbms_redefinition包将非分区表转化为分区表。

1.创建一张非分区表
CREATE TABLE unpar_table (
id NUMBER(10),
create_date DATE,
name VARCHAR2(100)
);

2.在表上创建一些约束
ALTER TABLE unpar_table ADD (
CONSTRAINT unpar_table_pk PRIMARY KEY (id)
);
CREATE INDEX create_date_ind ON unpar_table(create_date);

3.生成数据
declare
time_rdm number(5);
indate DATE;
a1 varchar2(20);
v_sql varchar2(2000);
begin
for i in 1..100000 loop
select trunc(dbms_random.value(0,500)) into time_rdm from dual;
select sysdate-time_rdm into indate from dual;
select dbms_random.string('u', 1)||lpad(to_char(trunc(dbms_random.value(1, 1000))),5,0)||dbms_random.string('l', 3) into a1 from dual;
v_sql:='insert into unpar_table values('||i||','''||indate||''','''||a1||''')';
execute immediate v_sql;
if mod(i,1000)=0 then
commit;
end if;
end loop;
end;
/

4.分析该表,至此,实验环境已经完成。后面来时进行重定义转换过程。
EXEC DBMS_STATS.gather_table_stats('LDY', 'unpar_table', cascade => TRUE);
 
5.创建一张分区过度表
CREATE TABLE par_table (
id NUMBER(10),
create_date DATE,
name VARCHAR2(100)
)
PARTITION BY RANGE (create_date)
(
PARTITION unpar_table_200904 VALUES LESS THAN (TO_DATE('01/05/2009', 'DD/MM/YYYY')),
PARTITION unpar_table_200905 VALUES LESS THAN (TO_DATE('01/06/2009', 'DD/MM/YYYY')),
PARTITION unpar_table_200906 VALUES LESS THAN (TO_DATE('01/07/2009', 'DD/MM/YYYY')),
PARTITION unpar_table_200907 VALUES LESS THAN (TO_DATE('01/08/2009', 'DD/MM/YYYY')),
PARTITION unpar_table_200908 VALUES LESS THAN (TO_DATE('01/09/2009', 'DD/MM/YYYY')),
PARTITION unpar_table_200909 VALUES LESS THAN (TO_DATE('01/10/2009', 'DD/MM/YYYY')),
PARTITION unpar_table_200910 VALUES LESS THAN (TO_DATE('01/11/2009', 'DD/MM/YYYY')),
PARTITION unpar_table_200911 VALUES LESS THAN (TO_DATE('01/12/2009', 'DD/MM/YYYY')),
PARTITION unpar_table_200912 VALUES LESS THAN (TO_DATE('01/01/2010', 'DD/MM/YYYY')),
PARTITION unpar_table_201001 VALUES LESS THAN (TO_DATE('01/02/2010', 'DD/MM/YYYY')),
PARTITION unpar_table_201002 VALUES LESS THAN (TO_DATE('01/03/2010', 'DD/MM/YYYY')),
PARTITION unpar_table_201003 VALUES LESS THAN (TO_DATE('01/04/2010', 'DD/MM/YYYY')),
PARTITION unpar_table_201004 VALUES LESS THAN (TO_DATE('01/05/2010', 'DD/MM/YYYY')),
PARTITION unpar_table_201005 VALUES LESS THAN (TO_DATE('01/06/2010', 'DD/MM/YYYY')),
PARTITION unpar_table_201006 VALUES LESS THAN (TO_DATE('01/07/2010', 'DD/MM/YYYY')),
PARTITION unpar_table_201007 VALUES LESS THAN (TO_DATE('01/08/2010', 'DD/MM/YYYY')),
PARTITION unpar_table_201008 VALUES LESS THAN (TO_DATE('01/09/2010', 'DD/MM/YYYY')),
PARTITION unpar_table_201009 VALUES LESS THAN (TO_DATE('01/10/2010', 'DD/MM/YYYY')),
PARTITION unpar_table_201010 VALUES LESS THAN (TO_DATE('01/11/2010', 'DD/MM/YYYY')),
PARTITION unpar_table_201011 VALUES LESS THAN (TO_DATE('01/12/2010', 'DD/MM/YYYY')),
PARTITION unpar_table_201012 VALUES LESS THAN (TO_DATE('01/01/2011', 'DD/MM/YYYY')),
PARTITION unpar_table_2011 VALUES LESS THAN (MAXVALUE));
 
 
5.开始重定义

a)检查是否满足重定义。
EXEC Dbms_Redefinition.can_redef_table('LDY', 'unpar_table');
 
 
b)如果没有返回错误,用下面的命令开始重定义:
BEGIN
DBMS_REDEFINITION.start_redef_table(
uname => USER, 
orig_table => 'unpar_table',
int_table => 'par_table');
END;
/
此过程需要一段时间才能完成。
 
 
c)在创建索引之前,原表上可能会产生一些新数据,需要隔段时间同步一下,这是为了之后的创建索引,以及收集统计信息更准确。
BEGIN
dbms_redefinition.sync_interim_table(
uname => 'LDY', 
orig_table => 'unpar_table',
int_table => 'par_table');
END;
/
此过程较快

d)创建约束和索引:
 
ALTER TABLE par_table ADD (
CONSTRAINT unpar_table_pk2 PRIMARY KEY (id)
);
CREATE INDEX create_date_ind2 ON par_table(create_date);

e)收集新表的统计信息:
EXEC DBMS_STATS.gather_table_stats('LDY', 'par_table', cascade => TRUE);

f)完成重定义:
BEGIN
dbms_redefinition.finish_redef_table(
uname => 'LDY',
orig_table => 'unpar_table',
int_table => 'par_table');
END;
/
 
在该点完成之后,原来的过度表变成了正式表了,在数据字典中两张表的名称进行了互换,并且原表上新增的数据也同步到了原过度表上。
原来的unpar_table名称变成了par_table,还是非分区表。
原来的过度表par_table名称变成了unpar_table,是分区表。

g)删除现在名称为par_table的非分区表。
DROP TABLE par_table;

h)重命名所有的约束名称,恢复成原始名称。
ALTER TABLE unpar_table RENAME CONSTRAINT unpar_table_pk2 TO unpar_table_pk;
ALTER INDEX create_date_ind2 RENAME TO create_date_ind;

i)检查表信息:

SQL> SELECT partitioned
  2  FROM user_tables
  3  WHERE table_name = 'UNPAR_TABLE';
PAR
---
YES

SQL> SELECT partition_name
  2  FROM user_tab_partitions
  3  WHERE table_name = 'UNPAR_TABLE';
PARTITION_NAME
------------------------------
UNPAR_TABLE_200904
UNPAR_TABLE_200905
UNPAR_TABLE_200906
UNPAR_TABLE_200907
UNPAR_TABLE_200908
UNPAR_TABLE_200909
UNPAR_TABLE_200910
UNPAR_TABLE_200911
UNPAR_TABLE_200912
UNPAR_TABLE_201001
UNPAR_TABLE_201002
UNPAR_TABLE_201003
UNPAR_TABLE_201004
UNPAR_TABLE_201005
UNPAR_TABLE_201006
UNPAR_TABLE_201007
UNPAR_TABLE_201008
UNPAR_TABLE_201009
UNPAR_TABLE_201010
UNPAR_TABLE_201011
UNPAR_TABLE_201012
UNPAR_TABLE_2011
已选择22行。

至此重定义完成,将unpar_table转变成了分区表。
 
在线重定义的一些约束:
1.需要有足够的空间来存放该表的2份数据。
2.不能变更主键的字段
3.表必须有主键
4.重定义只能在相同的schema中
5.在重定义完成之前增加新列不能指定NOT NULL
6.表不能包含LONG、BFILE、或用户定义类型的字段。
7.簇表不能重定义
8.SYS、SYSTEM的表不能重定义
9.表上有物化视图日志,或表上有定义物化视图,不能重定义
10.Horizontal sub setting of data cannot be performed during the redefinition
阅读(2472) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~