一 、oracle 高水位線詳解
一、什麼是水線(High Water Mark )?
所有的 oracle 段(segments,在此,為了了解友善,建議把 segment 作為表的一個同義詞) 都有一個在段内容納資料的上限,我們把這個上限稱為"high water mark"或 HWM。這個 HWM 是一個标記,用來說明已經有多少沒有使用的資料塊配置設定給這個 segment。HWM 通常增長的幅度為一次5個資料塊,原則上 HWM 隻會增大,不會縮小,即使将表中的資料全部删除,HWM 還是為原值,由于這個特點,使 HWM 很象一個水庫的曆史最高水位,這也就是 HWM的原始含義,當然不能說一個水庫沒水了,就說該水庫的曆史最高水位為0。但是如果我們在表上使用了 truncate指令,則該表的 HWM 會被重新置為0.
二、HWM 資料庫的操作有如下影響:
a) 全表掃描通常要讀出直到 HWM 标記的所有的屬于該表資料庫塊,即使該表中沒有任何資料。
b) 即使 HWM 以下有空閑的資料庫塊,鍵入在插入資料時使用了 append 關鍵字,則在插入時使用 HWM 以上的資料塊,此時 HWM 會自動增大
三、如何知道一個表的 HWM?
- a) 首先對表進行分析:
ANALYZE TABLE <tablename> ESTIMATE/COMPUTE STATISTICS;b) SELECT blocks, empty_blocks, num_rowsFROM user_tablesWHERE table_name = <tablename>; ---說明:BLOCKS 列代表該表中曾經使用過得資料庫塊的數目,即水線。EMPTY_BLOCKS 代表配置設定給該表,但是在水線以上的資料庫塊,即從來沒有使用的資料
---讓我們以一個有28672行的 BIG_EMP1表為例進行說明: 1) SQL> SELECT segment_name, segment_type, blocksFROM dba_segmentsWHERE segment_name='BIG_EMP1'; SEGMENTNAME SEGMENTTYPE BLOCK ----------------- -------------- --------- BIG_EMP1 TABLE 1024 1 row selected. 2) SQL> ANALYZE TABLE big_emp1 ESTIMATE STATISTICS;Statement processed. 3) SQL> SELECT table_name,num_rows,blocks,empty_blocksFROM user_tablesWHERE table_name='BIG_EMP1'; TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOC ---------- -------- ------- ------------- BIG_EMP1 28672 700 323 1 row selected. ---注意:BLOCKS + EMPTY_BLOCKS (700+323=1023)比 DBA_SEGMENTS.BLOCKS 少1個資料庫塊,這是因為有一個資料庫塊被保留用作 segment header。DBA_SEGMENTS.BLOCKS 表示配置設定給這個表的所有的資料庫塊的數目。USERTABLES.BLOCKS 表示已經使用過的資料庫塊的數目。 4) SQL> SELECT COUNT (DISTINCTDBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)||DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) "Used"FROM big_emp1; Used ---------- 700 1 row selected 5) SQL> delete from big_emp1;28672 rows processed. 6) SQL> commit;Statement processed. 7) SQL> ANALYZE TABLE big_emp1 ESTIMATE STATISTICS;Statement processed. 8) SQL> SELECT table_name,num_rows,blocks,empty_blocksFROM user_tablesWHERE table_name='BIG_EMP1'; TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS --------- -------- ------- ---------- BIG_EMP1 0 700 323 1 row selected. 9) SQL> SELECT COUNT (DISTINCTDBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)||DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) "Used"FROM big_emp1; Used ---------- 0 -----這表名沒有任何資料庫塊容納資料,即表中無資料1 row selected. 10) SQL> TRUNCATE TABLE big_emp1; Statement processe 11) SQL> ANALYZE TABLE big_emp1 ESTIMATE STATISTICS; Statement processed. 12) SQL> SELECT table_name,num_rows,blocks,empty_blocks FROM user_tables WHERE table_name='BIG_EMP1'; TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS ---------- -------- -------- ------------ BIG_EMP1 0 0 511 1 row selected. 13) SQL> SELECT segment_name,segment_type,blocksFROM dba_segmentsWHERE segment_name='BIG_EMP1'; SEGMENT_NAME SEGMENT_TYPE BLOCKS ------------ ------------- ------ BIG_EMP1 TABLE 512 1 row selecte -----TRUNCATE 指令回收了由 delete 指令産生的空閑空間,注意該表配置設定的空間由原先的1024塊降為512塊。為了保留由 delete 指令産生的空閑空間,可以使用 TRUNCATE TABLE big_emp1 REUSE STORAGE.用此指令後,該表還會是原先的1024
四、Oracle 表段中的高水位線 HWM
在 Oracle 資料的存儲中,可以把存儲空間想象為一個水庫,資料想象為水庫中的水。水庫中的水的位置有一條線叫做水位線,在 Oracle 中,這條線被稱為高水位線(High-warter mark, HWM)。在資料庫表剛建立的時候,由于沒有任何資料,是以這個時候水位線是空的,也就是說 HWM 為最低值。當插入了資料以後,高水位線就會上漲,但是這裡也有一個特性,就是如果你采用 delete 語句删除資料的話,資料雖然被删除了,但是高水位線沒有降低,還是剛剛删除資料以前的那麼高的水位線。也就是說:這條水位線在日常的增删操作中隻會上漲,不會下跌。
下面我們來談一下 Oracle 中 Select 語句的特性。Select 語句會對表中的資料進行一次掃描,但是究竟掃描多少資料存儲塊呢,這個并不是說資料庫中有多少資料,Oracle 就掃描這麼大的資料塊,而是 Oracle 會掃描高水位線以下的資料塊。現在來想象一下,如果剛才是一張剛剛建立的空表,你進行了一次 Select 操作,那麼由于高水位線 HWM 在最低的0位置上,是以沒有資料塊需要被掃描,掃描時間會極短。而如果這個時候你首先插入了一千萬條資料,然後再用 delete 語句删除這一千萬條資料。由于插入了一千萬條資料,是以這個時候的高水位線就在一千萬條資料這裡。後來删除這一千萬條資料的時候,由于 delete 語句不影響高水位線,是以高水位線依然在一千萬條資料這裡。這個時候再一次用 select 語句進行掃描,雖然這個時候表中沒有資料,但是由于掃描是按照高水位線來的,是以需要把一千萬條資料的存儲空間都要掃描一次,也就是說這次掃描所需要的時間和掃描一千萬條資料所需要的時間是一樣多的。是以有時候有人總是經常說,怎麼我的表中沒有幾條資料,但是還是這麼慢呢,這個時候其實奧秘就是這裡的高水位線了。
那有沒有辦法讓高水位線下降呢,其實有一種比較簡單的方法,那就是采用 TRUNCATE 語句進行删除資料。采用TRUNCATE 語句删除一個表的資料的時候,類似于重建立立了表,不僅把資料都删除了,還把 HWM 給清空恢複為0。是以如果需要把表清空,在有可能利用 TRUNCATE 語句來删除資料的時候就利用 TRUNCATE 語句來删除表,特别是那種資料量有可能很大的臨時存儲
在手動段空間管理(Manual Segment Space Management)中,段中隻有一個 HWM,但是在 Oracle9iRelease1才添加的自動段空間管理(Automatic Segment Space Management)中,又有了一個低 HWM 的概念出來。為什麼有了 HWM 還又有一個低 HWM 呢,這個是因為自動段空間管理的特性造成的。在手段段空間管理中,當資料插入以後,如果是插入到新的資料塊中,資料塊就會被自動格式化等待資料通路。而在自動段空間管理中,資料插入到新的資料塊以後,資料塊并沒有被格式化,而是在第一次在第一次通路這個資料塊的時候才格式化這個塊。是以我們又需要一條水位線,用來标示已經被格式化的塊。這條水位線就叫做低 HWM。一般來說,低 HWM 肯定是低于等于HWM 的。
五、修正 ORACLE 表的高水位線
在 ORACLE 中,執行對表的删除操作不會降低該表的高水位線。而全表掃描将始終讀取一個段(extent)中所有低于高水位線标記的塊。如果在執行删除操作後不降低高水位線标記,則将導緻查詢語句的性能低下。下面的方法都可以降低高水位線标記。
1.執行表重建指令 alter table table_name move;
(線上轉移表空間 ALTER TABLE 。。。 MOVE TABLESPACE 。。。ALTER TABLE 。。。 MOVE 後面不跟參數也行,不跟參數表還是在原來的表空間,move 後記住重建索引。如果以後還要繼續向這個表增加資料,沒有必要 move,隻是釋放出來的空間,隻能這個表用,其他的表或者 segment 無法使用該空間)
2.執行 alter table table_name shrink space;
注意,此指令為 Oracle 10g 新增功能,再執行該指令之前必須允許行移動 alter table table_name enable row movement;
實質上構造一個新表(在内部表現為一系列的 DML 操作,即将副本插入新位置,删除原來位置的記錄)靠近末尾處(右端)資料塊中的記錄往開始處(左端)的空閑空間處移動(DML 操作),不會引起 DML 觸發器當所有可能的移動被完成,高水位線将會往左端移動(DDL 操作)
新的高水位線右邊的空閑空間被釋放(DDL 操作)
實作前提條件:必須啟用行記錄轉移(enable row movement)僅僅适用于堆表,且位于自動段空間管理的表空間(堆表包括:标準表,分區表,物化視圖容器,物化視圖日志表)
3.複制要保留的資料到臨時表 t,drop 原表,然後 rename 臨時表 t 為原表
4.emp/imp
5.alter table table_name deallocate unused
6.盡量 truncate
為人:謙遜、激情、博學、審問、慎思、明辨、 笃行
學問:紙上得來終覺淺,絕知此事要躬行
為事:工欲善其事,必先利其器。
轉載請标注出處!