oracle的高水位線(HWM)

OraFige發表於2011-11-23
由之前的面試題一中學到的知識。

  現在解釋下什麼是“高水位”:

  oracle的邏輯儲存結構:表空間——>段——>區——>塊

  塊:是粒度最小的儲存單位,現在標準的塊大小是8K,ORACLE每一次I/O操作也是按塊來操作的,也就是說當ORACLE從資料檔案讀資料時,是讀取多少個塊,而不是多少行.

  區:由一系列相鄰的塊而組成,這也是ORACLE空間分配的基本單位,舉個例子來說,當我們建立一個表A時,首先ORACLE會分配一區的空間給這個表,隨著不斷的INSERT資料到A,原來的這個區容不下插入的資料時,ORACLE是以區為單位進行擴充套件的,也就是說再分配多少個區給A,而不是多少個塊.

  段:是由一系列的區所組成,一般來說,當建立一個物件時(表,索引),就會分配一個段給這個物件.所以從某種意義上來說,段就是某種特定的資料.如CREATE TABLE PM_USER,這個段就是資料段,而CREATE INDEX ON PM_USER(NAME),ORACLE同樣會分配一個段給這個索引,但這是一個索引段了.查詢段的資訊可以通過資料字典: SELECT * FROM USER_SEGMENTS來獲得,

  表空間:包含段,區及塊.表空間的資料物理上儲存在其所在的資料檔案中.一個資料庫至少要有一個表空間.

  所有的oracle段都有一個在段內容納資料的上限,我們把這個上限稱為"high water mark"或HWM。這個HWM是一個標記,用來說明已經有多少沒有使用的資料塊分配給這個segment。

  HWM通常增長的幅度為一次5個資料塊,原則上HWM只會增大,不會縮小,即使將表中的資料全部刪除,HWM還是為原值,由於這個特點,使 HWM很象一個水庫的歷史最高水位,這也就是HWM的原始含義,當然不能說一個水庫沒水了,就說該水庫的歷史最高水位為0。但是如果我們在表上使用了 truncate命令,則該表的HWM會被重新置為0。

  如何知道一個表的HWM?

  a) 首先對錶進行分析:

  ANALYZE TABLE ESTIMATE/COMPUTE STATISTICS;

  b) 檢視相關資訊:

  SELECT blocks, empty_blocks, num_rows FROM user_tables WHERE table_name =;

  [SYS@orcl] SQL>select segment_name,segment_type,blocks from dba_segments where segment_name='A';

  SEGMENT_NAME SEGMENT_TYPE BLOCKS

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

  A                  TABLE      8

  可得到A表分配了8個blocks。

  [TEST1@orcl] SQL>analyze table a compute statistics;

  表已分析。

  [TEST1@orcl] SQL>select num_rows,blocks,empty_blocks from user_tables where table_name='A'; 來源:考試大-Oracle認證考試

NUM_ROWS     BLOCKS EMPTY_BLOCKS

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

  1          5            3

  BLOCKS 列代表該表中曾經使用過得資料庫塊的數目,即水線。EMPTY_BLOCKS 代表分配給該表,但是在水線以上的資料庫塊,即從來沒有使用的資料塊.

  [TEST1@orcl] SQL>delete from a;

  [TEST1@orcl] SQL>analyze table a compute statistics;

  表已分析。

  [TEST1@orcl] SQL>select num_rows,blocks,empty_blocks from user_tables where table_name='A';

  NUM_ROWS     BLOCKS EMPTY_BLOCKS

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

  0          5            3

  [TEST1@orcl] SQL>select count(distinct dbms_rowid.rowid_block_number(rowid)||

  2 dbms_rowid.rowid_relative_fno(rowid)) "used" from a;

  used

  ----------

  0    注:Used = 0 這表名沒有任何資料庫塊容納資料,即表中無資料

  [TEST1@orcl] SQL>truncate table a;

  表被截斷。

  [TEST1@orcl] SQL>analyze table a compute statistics;

  表已分析。

  [TEST1@orcl] SQL>select table_name,blocks,empty_blocks from user_tables where table_name='A';

TABLE_NAME     BLOCKS EMPTY_BLOCKS

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

  A                   0            8

  注意:TRUNCATE命令回收了由delete命令產生的空閒空間。假如表原有1024塊,使用TRUNCATE後該表分配的空間降為512 塊。為了保留由delete命令產生的空閒空間,可以使用TRUNCATE TABLE TEST REUSE STORAGE用此命令後,該表還會是原先的1024塊。

  HWM的一些特性

  1 oracle用HWM來界定一個段中使用的塊和未使用的塊。

  當我們建立一個表:A時,ORACLE就會為這個物件分配一個段.在這個段中,即使我們未插入任何記錄,也至少有一個區(64bit,也就是8 個塊)被分配,第一個區的第一個塊就稱為段頭(SEGMENT HEADE),段頭中就儲存了一些資訊,基中HWM的資訊就儲存在此.此時,因為第一個區的第一塊用於儲存段頭的一些資訊,雖然沒有儲存任何實際的記錄, 但也算是被使用,此時HWM是位於第2個塊.當我們不斷插入資料到A後,第1個塊已經放不下後面新插入的資料,此時,ORACLE將高水位之上的塊用於儲存新增資料,同時,HWM本身也向上移.也就是說,當我們不斷插入資料時,HWM會不斷上移,這樣,在HWM之下的,就表示使用過的塊,HWM之上的就表示已分配但從未使用過的塊.

  2 HWM在插入資料時,當現有空間不足而進行空間的擴充套件時會向上移,但刪除資料時不會往下移.

  這就好比是水庫的水位,當漲水時,水位往上移,當水退出後,最高水位的痕跡還是清淅可見.

  刪除資料後便存在浪費的空間,ORACLE 不會釋放空間以供其他物件使用,有一條簡單的理由:由於空間是為新插入的行保留的,並且要適應現有行的增長。被佔用的最高空間稱為最高使用標記 (HWM)。

  3 HWM的資訊儲存在段頭當中.

  HWM本身的資訊是儲存在段頭.在段空間是手工管理方式時,ORACLE是通過FREELIST(一個單向連結串列)來管理段內的空間分配.在段空間是自動管理方式時(ASSM),ORACLE是通過BITMAP來管理段內的空間分配.

  4 ORACLE的全表掃描是讀取高水位標記(HWM)以下的所有塊

  當使用者發出一個全表掃描時,ORACLE 始終必須從段一直掃描到 HWM,即使它什麼也沒有發現。該任務延長了全表掃描的時間。

  採用TRUNCATE語句刪除一個表的資料的時候,類似於重新建立了表,不僅把資料都刪除了,還把HWM給清空恢復為0。

  5 當用直接路徑插入行時 — 例如,通過直接載入插入(用 APPEND 提示插入)或通過 SQL*LOADER 直接路徑 — 資料塊直接置於 HWM 之上。它下面的空間就浪費掉了

  在手動段空間管理(Manual Segment Space Management)中,段中只有一個HWM,但是在Oracle 9i Release1才新增的自動段空間管理(Automatic Segment Space Management)中,又有了一個低HWM的概念出來。為什麼有了HWM還又有一個低HWM呢,這個是因為自動段空間管理的特性造成的。在手段段空間管理中,當資料插入以後,如果是插入到新的資料塊中,資料塊就會被自動格式化等待資料訪問。而在自動段空間管理中,資料插入到新的資料塊以後,資料塊並沒有被格式化,而是在第一次訪問這個資料塊的時候才格式化這個塊。所以我們又需要一條水位線,用來標示已經被格式化的塊。這條水位線就叫做低HWM。一般來說,低HWM肯定是低於等於HWM的

額外擴充套件:

  [TEST1@orcl] SQL>delete from c;

  [TEST1@orcl] SQL>alter table c shrink space;

  alter table c shrink space

  *

  第 1 行出現錯誤:

  ORA-10636: ROW MOVEMENT is not enabled

  [TEST1@orcl] SQL>alter table c enable row movement;

  表已更改。

  [TEST1@orcl] SQL>alter table c shrink space;

  表已更改。

  [TEST1@orcl] SQL>analyze table c compute statistics;

  [TEST1@orcl] SQL>select table_name,blocks,empty_blocks from user_tables where table_name='C';

  TABLE_NAME     BLOCKS EMPTY_BLOCKS

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

  C                   1            7

  6. 修正ORACLE表的高水位線

  在ORACLE中,執行對錶的刪除操作不會降低該表的高水位線。而全表掃描將始終讀取一個段(extent)中所有低於高水位線標記的塊。如果在執行刪除操作後不降低高水位線標記,則將導致查詢語句的效能低下。

  下面的方法都可以降低高水位線標記。

  (1). 執行表重建指令 alter table table_name move;

  線上轉移表空間ALTER TABLE ... MOVE TABLESPACE ..

  當你建立了一個物件如表以後,不管你有沒有插入資料,它都會佔用一些塊,ORACLE也會給它分配必要的空間.同樣,用ALTER TABLE MOVE釋放自由空間後,還是保留了一些空間給這個表.

  ALTER TABLE ... MOVE 後面不跟引數也行,不跟參數列還是在原來的表空間,Move後記住重建索引。如果以後還要繼續向這個表增加資料,沒有必要move,只是釋放出來的空間,只能這個表用,其他的表或者segment無法使用該空間。

  (2). 執行alter table table_name shrink space;

  注意,此命令為Oracle 10g新增功能,再執行該指令之前必須允許行移動 alter table table_name enable row movement;

  如果要同時壓縮表的索引:ALTER TABLE TEST_TAB SHRINK SPACE CASCADE

  (3). 複製要保留的資料到臨時表t,drop原表,然後rename臨時表t為原表

  (4). 用邏輯匯入匯出: Emp/Imp

  (5). Alter table table_name deallocate unused

  注:這證明,DEALLOCATE UNUSED為釋放HWM上面的未使用空間,但是並不會釋放HWM下面的自由空間,也不會移動HWM的位置.

  (6). 儘量使用truncate.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26464953/viewspace-711865/,如需轉載,請註明出處,否則將追究法律責任。

相關文章