【轉】Oracle:MOVE與SHRINK命令相比較

ljm0211發表於2012-06-20

Move命令壓縮Oracle塊中的記錄、解決行連結問題,並重置表的高水平線。
  move和shrink命令都會重置表的高水平線,那麼哪個命令更有效呢?這篇文章討論使用move和shrink命令重新組織一個表,然後比較Oracle塊的記錄被壓縮得怎麼樣以及行連結解決得怎麼樣。

  注意:關於表高水平線和重置表高水平線的不同方法的詳細討論不在這篇文章的討論範圍內。

  下面的步驟簡要描述了使用move和shrink命令對TEMP_JP表進行重組時對該表的各種操作。在這一系列步驟中出現的一些異常被清晰地標註出來(Move相關的命令是以藍色表示,Shrink相關的命令是以綠色表示)。


01 – 03
 建立表temp_jp並插入2500條記錄到這個表中。
 
04
 顯示在表的Oracle塊中的記錄分配。

 

奇怪的是,插入到每個Oracle塊中的記錄數不是相同的。
 
05
 索引表temp_jp。
 
06
 檢驗表和索引的磁碟空間利用情況。

預設情況下,Oracle為一個表分配一個區間,為一個索引分配兩個區間。
 
07
 對temp_jp表新增一個第三列來模擬行連結。
 
08
 分析Temp_jp表。
 
09
 從temp_jp表選擇行數和連結行數。

temp_jp表中幾乎所有的記錄都是連結的。
 
10
 在模擬行連結之後檢查表和索引的磁碟空間利用情況。

表temp_jp的磁碟空間使用增加了10番。
 
11
 刪除這個表的所有記錄,使這個表中每個Oracle塊只留一條記錄。
 
12
 在刪除記錄之後,展開顯示temp_jp表的記錄。

記錄的數目顯示了每個Oracle塊是一致的,因為我們刪除了這個表的所有記錄,這個表中每個Oracle塊只留一條記錄。
 
13
 分析Temp_jp表。
 
14
 從temp_jp表選擇行數和連結行數。
 
15
 檢查temp_jp表的索引狀態。它是VALID。
 
16
 16-A

對錶執行move操作。

16-BA

16-BB對temp_jp表執行shrink操作。
 
17
 17-A

在對錶執行了move操作之後,索引的狀態是不可用的。

17-B在對temp_jp表執行了操作之後,索引的狀態是無效的。
 
18
 顯示temp_jp表和它的索引的磁碟空間使用情況。

18-A

在進行move操作之後,對錶分配了一個區間,對索引分配了兩個區間。

18-B

在進行shrink操作之後,表和索引被分配了每個具有8個Oracle塊的區間。最初分配給索引的兩個區間下降為一個。
 
19
 展開顯示temp_jp表Oracle塊中的記錄。

19-A

在temp_jp表中的所有5條記錄被壓縮到一個Oracle塊中。

19-B

在temp_jp表中的所有5條記錄被擴充套件到3個Oracle塊中。
 
20
 20-AA

表分析操作失敗,錯誤為ORA-01502。

20-AB

在表上重新建立索引來使其生效。

在索引重建操作之後,一個Oracle區間被分配給了這個索引。

20-AC

在索引重建之後,分析這個表。

20-B

分析這個表。
 
21
 選擇temp_jp表的行數和行連結數。

21-A

在對temp_jp表進行move操作之後,行連結被解決了,連結行數為0。

21-B

在對temp_jp表進行shrink操作之後,行連結沒有解決。連結行數為2.
 
22
 檢驗temp_jp表的索引狀態是有效的。
 


  測試A

  move操作怎樣影響一個表的Oracle塊中行連結和資料的分配:

  01-A

  drop table temp_jp;

  02-A

  create table temp_jp(col1 number(10),col2 varchar2(20)) tablespace users;

  03-A


declare
  begin
  for i in 1..2500 loop
  insert into temp_jp values(i,'RAMA');
  end loop;
  commit;
  end;
  /


  04-A


select dbms_rowid.rowid_relative_fno(rowid) ,
  dbms_rowid.rowid_block_number(rowid)  ,
  count(*)
  from temp_jp
  group by dbms_rowid.rowid_relative_fno(rowid),
  dbms_rowid.rowid_block_number(rowid)
  order by dbms_rowid.rowid_relative_fno(rowid), 
  dbms_rowid.rowid_block_number(rowid);
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)   COUNT(*)
------------------------------------ -------------------------- ----------
                                   4                                 2764        526
                                   4                                 2765        519
                                   4                                 2766        417
                                   4                                 2767        519
                                   4                                 2768        519
5 rows selected.


  05-A

  create index temp_jp_idx on temp_jp(col1) tablespace users;

  06-A


select segment_name,segment_type,bytes/1024/1024 mg,blocks,extents
  from user_segments where segment_name like 'TEMP%';
SEGMENT_NAME    SEGMENT_TYPE               MG     BLOCKS    EXTENTS
---------------         ------------------                 ----------  ----------        ----------
TEMP_JP           TABLE                    .0625          8          1
TEMP_JP_IDX      INDEX                     .125          16          2


  07-A


alter table temp_jp add(col3 varchar2(256) default 'THIS IS TO TEST THE ROW CHAINING ISSUE
WITH  MOVE COMMAND AND HOW THE DATA IS SPREAD BEFORE AND AFTER THE MOVE COMMAND IN EACH BLOCK OF THE TABLE');


  08-A

  analyze table temp_jp compute statistics;

  09-A


select table_name,num_rows,chain_cnt from user_tables where table_name='TEMP_JP';
TABLE_NAME                       NUM_ROWS  CHAIN_CNT
------------------------------        ----------     ----------
TEMP_JP                                2500           2426


  10-A


select segment_name,segment_type,bytes/1024/1024 mg,blocks,extents
  from user_segments where segment_name like 'TEMP%';
SEGMENT_NAME    SEGMENT_TYPE               MG     BLOCKS    EXTENTS
---------------         ------------------  ---------- ---------- ----------
TEMP_JP           TABLE                    .625         80         10
TEMP_JP_IDX      INDEX                    .125         16          2


  11-A


declare
   begin
   for c1 in (select DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) block,
    max(rowid) max_rowid
  from temp_jp group by DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)) loop
  for c2 in (select rowid,DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) block
    from temp_jp
  where DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)=c1.block) loop
  if ((c2.block = c1.block)  and (c2.rowid <> c1.max_rowid)) then
 delete from temp_jp where rowid = c2.rowid;
 end if;
 end loop;
 end loop;
commit;
 end;
  /


  12-A


select dbms_rowid.rowid_relative_fno(rowid) ,
      dbms_rowid.rowid_block_number(rowid)  ,
      count(*)
      from temp_jp
      group by dbms_rowid.rowid_relative_fno(rowid),
      dbms_rowid.rowid_block_number(rowid)
      order by dbms_rowid.rowid_relative_fno(rowid), 
      dbms_rowid.rowid_block_number(rowid);
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)   COUNT(*)
------------------------------------ ------------------------------------ ----------
                                   4                                 2764          1
                                   4                                 2765          1
                                   4                                 2766          1
                                   4                                 2767          1
                                   4                                 2768          1


  13-A

  analyze table temp_jp compute statistics;

  14-B


select table_name,num_rows,chain_cnt from user_tables where table_name='TEMP_JP';
TABLE_NAME               NUM_ROWS  CHAIN_CNT
------------------------------ ---------- ----------
TEMP_JP                                 5          5


  15-A


select index_name,status from user_indexes where table_name='TEMP_JP';
INDEX_NAME                     STATUS
------------------------------ --------
TEMP_JP_IDX                    VALID


  16-A

  alter table temp_jp move tablespace users;

  17-A


select index_name,status from user_indexes where table_name='TEMP_JP';
INDEX_NAME                     STATUS
------------------------------ --------
TEMP_JP_IDX                    UNUSABLE


  18-A


select segment_name,segment_type,bytes/1024/1024 mg,blocks,extents
     from user_segments where segment_name like 'TEMP%';
SEGMENT_NAME    SEGMENT_TYPE               MG     BLOCKS    EXTENTS
--------------- ------------------ ---------- ---------- ----------
TEMP_JP              TABLE               .0625          8          1
TEMP_JP_IDX     INDEX               .125         16          2


  19-A


select dbms_rowid.rowid_relative_fno(rowid) ,
         dbms_rowid.rowid_block_number(rowid)  ,
          count(*)
          from temp_jp
          group by dbms_rowid.rowid_relative_fno(rowid),
          dbms_rowid.rowid_block_number(rowid)
          order by dbms_rowid.rowid_relative_fno(rowid), 
          dbms_rowid.rowid_block_number(rowid);
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)   COUNT(*)
------------------------------------ ------------------------------------ ----------
                                   4                                 2908          5
 


  20-AA


analyze table temp_jp compute statistics;
analyze table temp_jp compute statistics
*
ERROR at line 1:
ORA-01502: index 'GZBGQT.TEMP_JP_IDX' or partition of such index is in unusable state


  20-AB

  alter index TEMP_JP_IDX rebuild online;

  20-AC

  analyze table temp_jp compute statistics;

  21-A


select table_name,num_rows,chain_cnt from user_tables where table_name='TEMP_JP';
TABLE_NAME                       NUM_ROWS  CHAIN_CNT
------------------------------ ---------- ----------
TEMP_JP                                 5          0


  22-A


select index_name,status from user_indexes where table_name='TEMP_JP';
INDEX_NAME                     STATUS
------------------------------ --------
TEMP_JP_IDX                    VALID


  測試B

  shrink操作怎樣影響一個表的Oracle塊中行連結和資料分配:

  01-B

  drop table temp_jp;

  02-B

  create table temp_jp(col1 number(10),col2 varchar2(20)) tablespace users;

  03-B

 

  declare
  begin
  for i in 1..2500 loop
  insert into temp_jp values(i,'RAMA');
  end loop;
  commit;
  end;
  /


  04-B


 select dbms_rowid.rowid_relative_fno(rowid) ,
   dbms_rowid.rowid_block_number(rowid)  ,
   count(*)
   from temp_jp
   group by dbms_rowid.rowid_relative_fno(rowid),
 dbms_rowid.rowid_block_number(rowid)
   order by dbms_rowid.rowid_relative_fno(rowid), 
 dbms_rowid.rowid_block_number(rowid);
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)   COUNT(*)
------------------------------------ ------------------------    ----------
                                   4                                 1908        526
                                   4                                 1909        519
                                   4                                 1910        417
                                   4                                 1911        519
                                   4                                 1912        519
5 rows selected.


  05-B

  create index temp_jp_idx on temp_jp(col1) tablespace users;

  06-B


select segment_name,segment_type,bytes/1024/1024 mg,blocks,extents
  from user_segments where segment_name like 'TEMP%';
SEGMENT_NAME    SEGMENT_TYPE               MG     BLOCKS    EXTENTS
---------------          ------------------        ----------  ----------      ----------
TEMP_JP                    TABLE                             .0625          8               1
TEMP_JP_IDX           INDEX                              .125          16              2


  07-B


alter table temp_jp add(col3 varchar2(256) default 'THIS IS TO TEST THE ROW CHAINING ISSUE WITH  MOVE
COMMAND AND HOW THE DATA IS SPREAD BEFORE AND AFTER THE MOVE COMMAND IN EACH
BLOCK OF THE TABLE');


  08-B

  analyze table temp_jp compute statistics;

  09-B


select table_name,num_rows,chain_cnt from user_tables where table_name='TEMP_JP';
TABLE_NAME                       NUM_ROWS  CHAIN_CNT
------------------------------        ----------    ----------
TEMP_JP                                2500                 2426


  10-B


select segment_name,segment_type,bytes/1024/1024 mg,blocks,extents
  from user_segments where segment_name like 'TEMP%';
SEGMENT_NAME    SEGMENT_TYPE               MG     BLOCKS    EXTENTS
---------------          ------------------         ----------  ----------      ----------
TEMP_JP         TABLE                            .625         80          10
TEMP_JP_IDX     INDEX                                    .125         16                  2


  11-B


declare
begin
for c1 in (select DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) block,
    max(rowid) max_rowid
           from temp_jp group by DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)) loop
for c2 in (select rowid,DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) block
           from temp_jp
           where DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)=c1.block) loop
if ((c2.block = c1.block) and (c2.rowid <> c1.max_rowid)) then
delete from temp_jp where rowid = c2.rowid;
end if;
end loop;
end loop;
commit;
end;
/


  12-B


select dbms_rowid.rowid_relative_fno(rowid) ,
  dbms_rowid.rowid_block_number(rowid)  ,
  count(*)
  from temp_jp
  group by dbms_rowid.rowid_relative_fno(rowid),
 dbms_rowid.rowid_block_number(rowid)
  order by dbms_rowid.rowid_relative_fno(rowid), 
 dbms_rowid.rowid_block_number(rowid);
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)   COUNT(*)
------------------------------------ --------------------------   ----------
                                   4                                 1908          1
                                   4                                 1909          1
                                   4                                 1910          1
                                   4                                 1911          1
                                   4                                 1912          1
5 rows selected.


  13-B

  analyze table temp_jp compute statistics;

  14-A


select table_name,num_rows,chain_cnt from user_tables where table_name='TEMP_JP';
TABLE_NAME                       NUM_ROWS  CHAIN_CNT
------------------------------         ----------             ----------
TEMP_JP                                 5                        5


  15-B


select index_name,status from user_indexes where table_name='TEMP_JP';
INDEX_NAME                     STATUS
------------------------------       --------
TEMP_JP_IDX                    VALID


  16-BA

  alter table temp_jp enable row movement;

  16-BB

  alter table temp_jp shrink space cascade;

  17-B


select index_name,status from user_indexes where table_name='TEMP_JP';
INDEX_NAME                     STATUS
--------------------------------------
TEMP_JP_IDX                    VALID


  18-B


select segment_name,segment_type,bytes/1024/1024 mg,blocks,extents
  from user_segments where segment_name like 'TEMP%';
SEGMENT_NAME    SEGMENT_TYPE               MG     BLOCKS    EXTENTS
-------------------------------------------  --------------------
TEMP_JP              TABLE                   .0625          8              1
TEMP_JP_IDX          INDEX                   .0625          8             1


  19-B


select dbms_rowid.rowid_relative_fno(rowid) ,
  dbms_rowid.rowid_block_number(rowid)  ,
  count(*)
  from temp_jp
  group by dbms_rowid.rowid_relative_fno(rowid),
  dbms_rowid.rowid_block_number(rowid)
  order by dbms_rowid.rowid_relative_fno(rowid), 
  dbms_rowid.rowid_block_number(rowid);
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)   COUNT(*)
------------------------------------ --------------------------  ----------
                                   4                                 1908          3
                                   4                                 1909          1
                                   4                                 1910          1


  20-B

  analyze table temp_jp compute statistics;

  21-B


select table_name,num_rows,chain_cnt from user_tables where table_name='TEMP_JP';
TABLE_NAME                       NUM_ROWS  CHAIN_CNT
------------------------------       ----------             ----------
TEMP_JP                                 5              2


  22-B


select index_name,status from user_indexes where table_name='TEMP_JP';
INDEX_NAME                     STATUS
------------------------------      --------
TEMP_JP_IDX                    VALID


  在對temp_jp表進行move操作之後,所有的記錄被壓縮排一個oracle塊中。在temp_jp表中的行連結問題被完全解決了。

  shrink不能完全解決表中行連結問題。表中留下的5條記錄被擴充套件到這個表的3個oracle塊中。

  在上面的比較之後,對於一個讀取要求較高、執行以毫秒來計的應用程式,我推薦使用move命令。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/11411056/viewspace-733415/,如需轉載,請註明出處,否則將追究法律責任。

相關文章