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_rows

FROM user_tables

WHERE table_name = <tablename>;

說明:

BLOCKS 列代表該表中曾經使用過得數據庫塊的數目,即水線。

EMPTY_BLOCKS 代表分配給該表,但是在水線以上的數據庫塊,即從來沒有使用的數據塊。

            

讓我們以一個有28672行的BIG_EMP1表爲例進行說明:

1) SQL> SELECT segment_name, segment_type, blocks

FROM dba_segments

WHERE segment_name='BIG_EMP1';

SEGMENT_NAME       SEGMENT_TYPE    BLOCKS     

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

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_blocks

FROM user_tables

WHERE table_name='BIG_EMP1';

TABLE_NAME  NUM_ROWS  BLOCKS     EMPTY_BLOCKS

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

BIG_EMP1    28672     700        323

1 row selected.

注意:

BLOCKS + EMPTY_BLOCKS (700+323=1023)比DBA_SEGMENTS.BLOCKS少1個數據庫塊,這是因爲有一個數據庫塊被保留用作segment header。DBA_SEGMENTS.BLOCKS 表示分配給這個表的所有的數據庫塊的數目。USER_TABLES.BLOCKS表示已經使用過的數據庫塊的數目。

             

4) SQL> SELECT COUNT (DISTINCT

DBMS_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_blocks

FROM user_tables

WHERE table_name='BIG_EMP1';

TABLE_NAME  NUM_ROWS   BLOCKS   EMPTY_BLOCKS

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

BIG_EMP1    0          700      323

1 row selected.

 

9) SQL> SELECT COUNT (DISTINCT

DBMS_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 processed.

                   

11) SQL> ANALYZE TABLE big_emp1 ESTIMATE STATISTICS;

Statement processed.

                   

12) SQL> SELECT table_name,num_rows,blocks,empty_blocks

2> FROM user_tables

3> 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,blocks

FROM dba_segments

WHERE segment_name='BIG_EMP1';

SEGMENT_NAME  SEGMENT_TYPE  BLOCKS

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

BIG_EMP1      TABLE         512

1 row selected.

注意:

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;執行完之後,表的索引不能用了,通過rebuild重新建立,具體操作可以參照ORACLE中index的rebuild

(在線轉移表空間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;

3.複製要保留的數據到臨時表t,drop原表,然後rename臨時表t爲原表

4.emp/imp

5.alter   table  table_name  deallocate   unused  

6.儘量truncate吧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章