4. High-Water Mark

在Oracle裡面有一個相當重要的觀念,High-Water Mark;所謂的High-Water Mark是指在這個High-Water Mark之上的Data Block是從未被使用過的,也就是說在Free List裡面並不包含這些Data Block,Free List只包含High-Water Mark以下的Data Block,如果當Oracle找不到可用的Data Block可用時,Oracle會先使High-Water Mark往後移5個Data Block,如果還可以往後移5格的話代表這個擴充區段(Extent)還有空間可以用,如此Free list裡面就會多5個Data Block的空間,如果沒有可用的Data Block,Oracle就會找找看還有沒有其他可用的擴充區段(Extent),如果沒有就會告訴Oracle沒有Extent了,必須擴充一塊新的Extent。如圖所示。
High-Water Mark的重點如下:
  • High-Water Mark以上的Data Block是不會出現在Free list裡面,如果不夠會在往後移5個Data Block。
  • 當使用者新增到Table裡面的時候,High-Water Mark可能會往後移。
  • 當刪除(Delete)資料後,是不會降低High-Water Mark,除非執行清空表格(Truncate Table)指令或重建Data Block,High-Water Mark才會重新設定。
  • High-Water Mark會在我們的Segment header裡面,也就是說Table的第一個Data Block會記錄這個table的High-Water Mark在哪裡。
  • 當Oracle做全表格掃描(Full Table Scan)時,會去讀取High-Water Mark以下所有的Data Block,這裡就有一個問題,當Table有一千萬筆資料時,如果執行select count(*) 時Oracle會針對此表格所在的每個Data Block詢問有幾筆資料,當所有的Data Block問完之後,最後在總加起來就是結果了 ,但如果刪除(Delete)了500萬筆資料,在作select count(*) Oracle還是會去詢問所有High-Water Mark以下所有的Data Block,所讀取的Data Block數量和一千萬筆資料時是一樣的,雖然有些Data Block是空的;因此雖然筆數不同但所執行的時間卻相同,只有清空表格(Truncate Table)才能把空間High-Water Mark重新設定;由此可知如果要把一個Table裡面的資料全部刪除,清空(Truncate)指令會比刪除(Delete)指令來的好。
確認High-Water Mark方式如下:

DECLARE
v_owner VARCHAR2(30) := 'USER_NAME' ;
v_segment_name VARCHAR2(30) := 'TEST_TABLE';
v_segment_type VARCHAR2(30) := 'TABLE';
v_total_blocks NUMBER;
v_total_bytes NUMBER;
v_unused_blocks NUMBER;
v_unused_bytes NUMBER;
v_last_used_extent_file_id NUMBER;
v_last_used_extent_block_id NUMBER;
v_last_used_block NUMBER;
BEGIN
dbms_space.unused_space(v_owner,
v_segment_name,
v_segment_type,
v_total_blocks,
v_total_bytes,
v_unused_blocks,
v_unused_bytes,
v_last_used_extent_file_id,
v_last_used_extent_block_id,
v_last_used_block
);
dbms_output.put_line(INITCAP(v_segment_type)||' :'||v_owner||'.'||v_segment_name);
dbms_output.put_line('Total Blocks :'||TO_CHAR(v_total_blocks));
dbms_output.put_line('Blocks above HWM :'||TO_CHAR(v_unused_blocks));
END;
/
Shank Space

通常Oracle的Table經過經年累月的DML後,常會發現效能還是不佳,那是因為High Water Mark,,造成Full Table Scan會從第一個Data Block掃瞄到HWM的位置,此時除了Table Move或Export再Import外,別無他法,但Oracle 10g開始支援縮小空間(Shrink Space) 這指令 。
此操作需要對Table加上Table Level的共用鎖定(TM:Row Exclusive),並對搬移資料列加上獨佔鎖定(Exclusive)‧ 然後將表格的資料盡可能地向區段標頭(Segment Header)靠攏,方法是使用一組新增、刪除資料操作,先新增新的資料,再刪除舊的資料,但新增的資料將儘可能靠近區段標頭,資料管理者可以線上重組Tab;e,而不會妨礙其他使用者對該Table進行DML操作。語法如下:

ALTER TABLE table_name SHRINK SPACE COMPACT;
但要注意的是該操作不會移動高水位標記(High Water Mark),也不會回收位於高水位標記以後的Data Block, 所以重組後的Table,僅僅只是改善非Full Talbe Scan以外的情形(例Index Fast Full Scan、Index Range Scan、Index Unique Scan等等)。






沒有留言:

張貼留言