Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103688036
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: Oracle

2008-04-20 21:07:05

   文章来源:    

 

  联机重组单个分区

  假设您有一个包含事务历史的表 TRANS。该表基于 TRANS_DATE 进行分区,每个季度作为一个分区。在正常的业务过程中,最新的分区经常更新。某个季度过后,该分区上可能没有很多活动了,因此可以将它移动到其他位置。但移动本身将需要对表进行锁定,从而拒绝对分区的公共访问。如何在不影响其可用性的情况下移动分区?

  在 Oracle 数据库 10g 第 2 版中,可以对单个分区使用联机重新定义。您可以像对整个表执行重新定义(使用 DBMS_REDEFINITION 程序包)一样执行此任务,但底层机制并不相同。常规表是通过对源表创建物化视图重新定义的,而单个分区是通过交换分区方法重新定义的。

  我们来看一下它的工作原理。以下是 TRANS 表的结构:
SQL> desc trans 
Name                              Null?Type 
 --------------------------------- -------- ------------------------- 
TRANS_ID                                   NUMBER 
TRANS_DATE                                 DATE 
TXN_TYPE                                   VARCHAR2(1) 
ACC_NO                                     NUMBER 
TX_AMT                                     NUMBER(12,2) 
STATUS      
  该表已经按如下所示进行了分区:
partition by range (trans_date) 
( 
partition y03q1 values less than (to_date('04/01/2003','mm/dd/yyyy')), 
partition y03q2 values less than (to_date('07/01/2003','mm/dd/yyyy')), 
partition y03q3 values less than (to_date('10/01/2003','mm/dd/yyyy')), 
partition y03q4 values less than (to_date('01/01/2004','mm/dd/yyyy')), 
partition y04q1 values less than (to_date('04/01/2004','mm/dd/yyyy')), 
partition y04q2 values less than (to_date('07/01/2004','mm/dd/yyyy')), 
partition y04q3 values less than (to_date('10/01/2004','mm/dd/yyyy')), 
partition y04q4 values less than (to_date('01/01/2005','mm/dd/yyyy')), 
partition y05q1 values less than (to_date('04/01/2005','mm/dd/yyyy')), 
partition y05q2 values less than (to_date('07/01/2005','mm/dd/yyyy')) 
) 

  在某个时刻,您决定将分区 Y03Q2 移动到另一个表空间 (TRANSY03Q2),该表空间可能位于一个不同类型的磁盘(一个慢一点、便宜一点的磁盘)上。为此,请首先确认您可以联机重新定义该表:
begin 
dbms_redefinition.can_redef_table(  
uname        => 'ARUP',   
tname        => 'TRANS',  
options_flag => dbms_redefinition.cons_use_rowid,  
part_name    => 'Y03Q2');  
end; 
/ 

  此处没有输出,因此您确认可以联机重新定义该表。接下来,创建一个临时表保存该分区的数据:
create table trans_temp 
( 
trans_id        number, 
trans_date date, 
txn_type varchar2(1), 
acc_no number, 
tx_amt number(12,2), 
status varchar2(1) 
) 
tablespace transy03q2 
/ 

  请注意,由于表 TRANS 进行了范围分区,因此您已经将该表定义为未分区表。该表在所需的表空间 TRANSY03Q2 中创建。如果表 TRANS 包含一些本地索引,则表示您已经对表 TRANS_TEMP 创建了这些索引(当然是创建为未分区索引)。

  现在,您就可以启动重新定义过程:
begin 
dbms_redefinition.start_redef_table(  
uname        => 'ARUP',   
orig_table   => 'TRANS',  
int_table    => 'TRANS_TEMP',  
col_mapping  => NULL,  
options_flag => dbms_redefinition.cons_use_rowid,  
part_name    => 'Y03Q2');  
end; 
/ 

  该调用有几个注意事项。第一,将参数 col_mapping 设置为 NULL;在单个分区重新定义中,该参数没有意义。第二,一个新参数 part_name 指定了要重新定义的分区。第三,注意其中没有 COPY_TABLE_DEPENDENTS 参数,该参数也没有意义,原因是表本身无法更改;只移动分区。

  如果该表很大,此操作可能持续很长时间;因此请在操作过程中对它进行同步。
begin 
dbms_redefinition.sync_interim_table(  
uname      => 'ARUP',   
orig_table => 'TRANS',  
int_table  => 'TRANS_TEMP',  
part_name  => 'Y03Q2');  
end; 
/ 

  最后,使用以下代码完成该过程
begin 
dbms_redefinition.finish_redef_table(  
uname      => 'ARUP',   
orig_table => 'TRANS',  
int_table  => 'TRANS_TEMP',  
part_name  => 'Y03Q2');  
end; 

  此时,分区 Y03Q2 位于表空间 TRANSY03Q2 中。如果该表存在任何全局索引,则它们将被标记为 UNUSABLE 并且必须被重新构建。

  单个分区重新定义对于跨表空间移动分区(一个常见的信息生命周期管理任务)很有用。但显而易见,其中存在几个限制。例如,您无法在重新定义过程中更改分区方法(即从范围更改为散列)或更改表的结构。

  逐块地删除表

  您注意到过删除一个分区的表需要多长时间吗?这是因为每个分区都是一个必须删除的段。在 Oracle 数据库 10g 第 2 版中,当您删除分区的表时,分区将逐个被删除。由于每个分区是单独删除的,因此所需的资源要比删除整个表少。

  要演示这个新行为,您可以使用 10046 跟踪跟踪该会话。
alter session set events '10046 trace name context forever, level 12'; 

  然后,删除该表。如果查看跟踪文件,则将看到分区表删除的代码:
delete from tabpart$ where bo# = :1 
delete from partobj$ where obj#=:1 
delete from partcol$ where obj#=:1 
delete from subpartcol$ where obj#=:1 

  请注意,分区是按顺序删除的。该方法最大限度地降低了删除过程中的资源使用率并增强了性能。
阅读(328) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~