关于oracle中Move机制的一点探讨

8i开始,oracle开始提供Move的命令。我们通常使用这个命令,将一个table segment从一个tablespace移动到另一个tablespace

Move实际上是在block之间物理的copy数据,那么,我们可以通过这种方式来降低tableHWM。我们先通过一个实验来看看move是如何移动数据的。创建table TEST_HWMinsert一些数据:

SQL> create table TEST_HWM (id int ,name char(2000)) tablespace hwm;

 

Table created

 

我们往table TEST_HWM insert如下数据:

insert into TEST_HWM values (1,'aa');

insert into TEST_HWM values (2,'bb');

insert into TEST_HWM values (2,'cc');

insert into TEST_HWM values (3,'dd');

insert into TEST_HWM values (4,'ds');

insert into TEST_HWM values (5,'dss');

insert into TEST_HWM values (6,'dss');

insert into TEST_HWM values (7,'ess');

insert into TEST_HWM values (8,'es');

insert into TEST_HWM values (9,'es');

insert into TEST_HWM values (10,'es');

 

我们来看看这个tablerowidblockID和信息:

SQL>  select rowid , id,name from TEST_HWM;

                                                 

ROWID                           ID     NAME

-------------------------          ----------- ------

AAAH7JAALAAAAAUAAA                1     aa

AAAH7JAALAAAAAUAAB                2     bb

AAAH7JAALAAAAAUAAC                2     cc

AAAH7JAALAAAAAVAAA                3     dd

AAAH7JAALAAAAAVAAB                4     ds

AAAH7JAALAAAAAVAAC                5     dss

AAAH7JAALAAAAAWAAA                6     dss

AAAH7JAALAAAAAWAAB                7     ess

AAAH7JAALAAAAAWAAC                8     es

AAAH7JAALAAAAAXAAA                9     es

AAAH7JAALAAAAAXAAB               10     es

SQL> select EXTENT_ID,FILE_ID,RELATIVE_FNO,BLOCK_ID,BLOCKS

  2  from dba_extents  where segment_name='TEST_HWM' ;

 

 EXTENT_ID    FILE_ID RELATIVE_FNO   BLOCK_ID     BLOCKS

---------- ---------- ------------ ---------- ----------

         0         11           11         19          5

 

这里,简单地介绍一下rowid的相关知识:

ROWID 磁盘10 个字的存储空间使用18 个字符来显示它包含下列组件:

 数据对象编号:个数据对象如表或索引在创建时分配有此编号,并且此编号在数据库中的;

相关文件编号:此编号对个表空间中的个文件的;

编号:表示包含此行的块在文件中的位置;

编号:中行目位置的位置;

在内部数据对象编号32 位,相关文件编号10 位,块编号22位行编号16 位,加80 位或10 个字节,ROWID 使用以64 基数的编码方案来显方案个位置用于数据对象,编号个位置用于相关文件编号个位置用于块编号个位置用于行编号64 基数的编码方案使用字A-Z a-z 0-9 + /64 个字符,示:

AAAH7J AAL AAAAAU AAA

在本例中

AAAH7J   数据对象编号

AAL       相关文件编号

AAAAAU  编号

AAA       编号

 

那么,我们根据数据的rowid,可以看出这11行数据分布在AAAAAUAAAAAVAAAAAWAAAAAX这四个block中。

然后我们从table TEST_HWMdelete一些数据:

delete from TEST_HWM where id = 2;

delete from TEST_HWM where id = 4;

delete from TEST_HWM where id = 3;

delete from TEST_HWM where id = 7;

delete from TEST_HWM where id = 8;

delete from TEST_HWM where id = 9;

 

我们在来看看这个tablerowidblockID和信息:

SQL> select rowid , id,name from TEST_HWM;

 

ROWID                      ID NAME

------------------ ---------- --------- --------------

AAAH7JAALAAAAAUAAA       1  aa

AAAH7JAALAAAAAVAAC       5  dss

AAAH7JAALAAAAAWAAA       6  dss

AAAH7JAALAAAAAXAAB       10  es

SQL> select EXTENT_ID,FILE_ID,RELATIVE_FNO,BLOCK_ID,BLOCKS

  2   from dba_extents  where segment_name='TEST_HWM' ;

 

 EXTENT_ID    FILE_ID RELATIVE_FNO   BLOCK_ID     BLOCKS

---------- ---------- ------------ ---------- ----------

         0         11           11         19          5

 

在这里,我们可以看到,数据的rowid没有发生改变,我们根据数据的rowid,可以看出这4行数据依然分布在AAAAAUAAAAAVAAAAAWAAAAAX这四个block中。

接下来我们对table TEST_HWM进行move的操作,然后再来观察rowidblockid的信息:

SQL> alter table TEST_HWM move;

Table altered

 

SQL> select rowid,id,name from HWM;

 

ROWID                       ID NAME

------------------ ---------- -------- ---------------

AAAH7NAALAAAANrAAA       1 aa

AAAH7NAALAAAANrAAB       5 dss

AAAH7NAALAAAANrAAC       6 dss

AAAH7NAALAAAANsAAA       10 es

 

SQL> select EXTENT_ID,FILE_ID,RELATIVE_FNO,BLOCK_ID,BLOCKS

  2   from dba_extents  where segment_name=' TEST_HWM ' ;

 

 EXTENT_ID    FILE_ID RELATIVE_FNO   BLOCK_ID     BLOCKS

---------- ---------- ------------ ---------- ----------

         0         11           11        874          5

 

 

我们可以看到,对table TEST_HWM进行move后,该table所在blockid发生了改变,那么数据的rowid自然也发生了改变。从上面的结果,我们可以看到,现在table TEST_HWM 的数据分布在AAAANrAAAANs两个block中了。但是这四行数据的rowid的顺序来看,这四行数据在table中的存储顺序并没有发生改变。这也就证明了,move是在block之间物理的copy数据。

 

我们再来看看move操作对于tableHWM的位置有什么变化,我们同样使用系统视图all_objects来创建测试table my_objects,然后delete9999行数据:

SQL> create table my_objects tablespace HWM

2        as select * from all_objects;

SQL> delete from my_objects where rownum<10000;

9999 rows deleted

SQL> select count(*) from my_objects;

  COUNT(*)

----------

     21015

SQL> exec show_space(p_segname => 'MY_OBJECTS',p_owner => 'DLINGER',p_type => 'TABLE');

Total Blocks............................425

Total Bytes.............................3481600

Unused Blocks...........................3

Unused Bytes............................24576

Last Used Ext FileId....................11

Last Used Ext BlockId...................1294

Last Used Block.........................2

 

这里HWM=425 - 3 + 1 = 423

然后对table MY_OBJECTS进行move操作:

SQL> alter table MY_OBJECTS move;

表已更改。

SQL> exec show_space(p_segname => 'MY_OBJECTS',p_owner => 'DLINGER',p_type => 'TABLE');

Total Blocks............................290

Total Bytes.............................2375680

Unused Blocks...........................1

Unused Bytes............................8192

Last Used Ext FileId....................11

Last Used Ext BlockId...................1584

Last Used Block.........................4

 

我们可以看到,table MY_OBJECTSHWM423移动到290tableHWM降低了!

 

我们还可以使用别的方法来降低tableHWM,比如CTASinsert into 等,那么move操作对redo logo的写和其他的方式比较起来是相对较少的,我们在这里就不列出把具体的实验结果了,大家有兴趣的可以自己动手来证实一下。

 

上面我们讨论了move的执行机制和如何使用move降低tableHWM,这里,我们补充说明move的另外一些用法,以及使用move时的一些要注意的问题。

 

Move的一些用法

以下是alter table move子句的完整语法,我们介绍其中的几点:

MOVE [ONLINE] 
     
     
  [segment_attributes_clause] 
     
     
  [data_segment_compression]
     
     
  [index_org_table_clause]
     
     
  [ { LOB_storage_clause | varray_col_properties }
     
     
    [ { LOB_storage_clause | varray_col_properties } ]...
     
     
  ]
     
     
  [parallel_clause]
     
     

 

a. 我们可以使用move将一个table从当前的tablespace上移动到另一个tablespace上,如:

alter table t move tablespace tablespace_name;

b. 我们还可以用move来改变table已有的block的存储参数,如:

alter table t move storage (initial 30k  next 50k);

 

另外,move操作也可以用来解决table中的行迁移的问题。

 

使用move的一些注意事项

 

a.       table上的index需要rebuild

在前面我们讨论过,move操作后,数据的rowid发生了改变,我们知道,index是通过rowidfetch数据行的,所以,table上的index是必须要rebuild的。

SQL>  create index i_my_objects on my_objects (object_id);

Index created

 

SQL> alter table my_objects move;

Table altered

 

SQL> select index_name,status from user_indexes where index_name='I_MY_OBJECTS';

 

INDEX_NAME                     STATUS

------------------------------ --------

I_MY_OBJECTS                   UNUSABLE

 

从这里可以看到,当table MY_OBJECTS进行move操作后,该table 上的inedx的状态为UNUSABLE,这时,我们可以使用alter index I_MY_OBJECTS rebuild online的命令,对index I_MY_OBJECTS进行在线rebuild

 

b.      move时对table的锁定

当我们对table MY_OBJECTS进行move操作时,查询v$locked_objects视图可以发现,table MY_OBJECTS上加了exclusive lock

SQL>select OBJECT_ID, SESSION_ID,ORACLE_USERNAME,LOCKED_MODE from v$locked_objects;

 

 OBJECT_ID SESSION_ID ORACLE_USERNAME    LOCKED_MODE

---------- ---------- ------------------ -----------

     32471          9 DLINGER                      6

SQL> select object_id from user_objects where object_name = 'MY_OBJECTS';

 

 OBJECT_ID

----------

     32471

这就意味着,table在进行move操作时,我们只能对它进行select的操作。反过来说,当我们的一个sessiontable进行DML操作且没有commit时,在另一个session中是不能对这个table进行move操作的,否则oracle会返回这样的错误信息:ORA-00054: 资源正忙,要求指定 NOWAIT

 

c.      关于move时空间使用的问题:

当我们使用alter table move来降低tableHWM时,有一点是需要注意的,这时,当前的tablespace中需要有1倍于table的空闲空间以供使用:

SQL> CREATE TABLESPACE TEST1

  2  DATAFILE 'D:/ORACLE/ORADATA/ORACLE9I/TEST1.dbf' SIZE 5M

  3  UNIFORM SIZE 128K ;


SQL> create table my_objects  tablespace test1 as select * from all_objects;

表已创建。


SQL> select bytes/1024/1024 from user_segments where segment_name='MY_OBJECTS';


BYTES/1024/1024

---------------

          3.125

 

SQL> alter table MY_OBJECTS move;


alter table MY_OBJECTS move

            *

ERROR 位于第 1 :

ORA-01652: 无法通过16(在表空间TEST1中)扩展 temp


SQL> ALTER DATABASE

  2  DATAFILE 'D:/ORACLE/ORADATA/ORACLE9I/TEST1.DBF' RESIZE   7M ;


数据库已更改。

SQL> alter table MY_OBJECTS move;

表已更改。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值