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
轉載請標註源文鏈接,否則追究法律責任!