淺析ORACLE數據庫高水位線(high water mark)

ORACLE數據庫邏輯結構包括:數據庫塊(block),擴展(extent 區),段(segment),表空間(tablespace)。高水位線就存在於段(segment)中,它用於標識段中已使用過的數據塊與未使用地的數據塊二者間交界,掃描表數據的時候,高水位線以下的所有數據塊都必須被掃描。

 

首先需要提醒大家,高水位線存在於段,且高水位線的位置記錄在段頭,也就是段的第一個數據塊中。因此,我們可以轉存儲段頭信息來看高水位信息。

 

段又有很多種,數據段,索引段,臨時段,回滾段等。當創建段的時候會分配區,區是由若干個物理連續的數據塊組成。區的分配是需要初始化數據塊的,默認初始化(format)單位爲1M。記住,高水位線並不是初始化的交界片,被初始化過的數據庫並不一定使用過。

 

以下通過實驗來進一步闡述高水位線:

 

創建測試表

SQL> create table hwm as select * from dba_segments;

Table created.

SQL> BEGIN
  DBMS_STATS.gather_table_stats('SYS','HWM');
END;
  2    3    4 
  5  /

PL/SQL procedure successfully completed.

SQL> select HEADER_FILE,HEADER_BLOCK from DBA_SEGMENTS where SEGMENT_NAME='HWM'
;

HEADER_FILE HEADER_BLOCK
----------- ------------
   1    89168

SQL> ALTER SYSTEM DUMP DATAFILE 1 BLOCK 89168;

 

  Extent Header:: spare1: 0      spare2: 0      #extents: 13     #blocks: 103
                  last map  0x00000000  #maps: 0      offset: 4128
      Highwater::  0x00415cb5  ext#: 12     blk#: 5      ext size: 8
  #blocks in seg. hdr's freelists: 0
  #blocks below: 100
  mapblk  0x00000000  offset: 12  

 

刪除3000行數據提交修改,再看看高水位線有沒有變化:

SQL> delete from hwm where rownum < 3000;

2999 rows deleted.

SQL> commit;

Commit complete.

SQL> alter system checkpoint;

System altered.

SQL> ALTER SYSTEM DUMP DATAFILE 1 BLOCK 89168;

  Extent Control Header
  -----------------------------------------------------------------
  Extent Header:: spare1: 0      spare2: 0      #extents: 13     #blocks: 103  
                  last map  0x00000000  #maps: 0      offset: 4128 
      Highwater::  0x00415cb5  ext#: 12     blk#: 5      ext size: 8    
  #blocks in seg. hdr's freelists: 0    
  #blocks below: 100  
  mapblk  0x00000000  offset: 12   

 

並沒有發現高水位線有變化,那麼插入2000行繼續觀察

SQL> insert into hwm select * from dba_segments where rownum < 2001;

2000 rows created.

SQL> commit;

Commit complete.

SQL> alter system checkpoint;

System altered.

SQL> ALTER SYSTEM DUMP DATAFILE 1 BLOCK 89168;

System altered.
 
  Extent Control Header
  -----------------------------------------------------------------
  Extent Header:: spare1: 0      spare2: 0      #extents: 13     #blocks: 103  
                  last map  0x00000000  #maps: 0      offset: 4128 
      Highwater::  0x00415cb5  ext#: 12     blk#: 5      ext size: 8    
  #blocks in seg. hdr's freelists: 0    
  #blocks below: 100  
  mapblk  0x00000000  offset: 12   
                   Unlocked
     Map Header:: next  0x00000000  #extents: 13   obj#: 84253  flag: 0x40000000

高水位線並沒有發生變化,說明高水位線以下的delete過的數據塊是可以被複用的.

 

此時如果再插入1000行,高水位線應該是會變化的,求證一下:

SQL> insert into hwm select * from dba_segments where rownum < 1001;

1000 rows created.

SQL> commit;

Commit complete.

SQL> alter system checkpoint;

System altered.

SQL> ALTER SYSTEM DUMP DATAFILE 1 BLOCK 89168;

System altered.

  Extent Header:: spare1: 0      spare2: 0      #extents: 13     #blocks: 103  
                  last map  0x00000000  #maps: 0      offset: 4128 
      Highwater::  0x00415cb5  ext#: 12     blk#: 5      ext size: 8    
  #blocks in seg. hdr's freelists: 3    
  #blocks below: 100  
  mapblk  0x00000000  offset: 12   
                   Unlocked
     Map Header:: next  0x00000000  #extents: 13   obj#: 84254  flag: 0x40000000

    
發現高水位線依舊沒有改變,繼續插入新數據並觀察:

SQL> insert into hwm select * from dba_segments where rownum < 1001;

1000 rows created.

SQL> commit;

Commit complete.

SQL> alter system checkpoint;

System altered.

SQL> ALTER SYSTEM DUMP DATAFILE 1 BLOCK 89168;

System altered.

 

  Extent Header:: spare1: 0      spare2: 0      #extents: 15     #blocks: 119  
                  last map  0x00000000  #maps: 0      offset: 4128 
      Highwater::  0x00415cc5  ext#: 14     blk#: 5      ext size: 8    
  #blocks in seg. hdr's freelists: 1    
  #blocks below: 116  
  mapblk  0x00000000  offset: 14   
                   Unlocked
     Map Header:: next  0x00000000  #extents: 15   obj#: 84254  flag: 0x40000000

 

以上可以看到,delete並不能回收表數據,在增刪改表數據庫的過程使得高水位線持續增長,且被刪除的數據記錄位置也無法100%複用,因此難免會存在碎片。比如,一張表100萬數據,將全表數據delete之後,高水位線位置依舊在第100萬行處,儘管此時表數據爲0行,但全表掃描時候仍然需要掃描所有已使用過的數據塊,全表掃描的效率將越來越低下。

因此oracle也提供了多種回收高水位線的方法,諸如:

  表重建, 如CATS(create table as select ...)

  導出導入(exp/imp,expdp/impdp)

  truncate(危險,因此慎用)

  shrink space

  move table

  DBMS_REDEFINITION表在線重定義

  等等

 

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

本文來自於我的技術博客 http://blog.csdn.net/robo23

轉載請標註源文鏈接,否則追究法律責任!

 

發佈了50 篇原創文章 · 獲贊 2 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章