深入瞭解oracle的高水位(HWM)

tolywang發表於2007-07-13
說到HWM,我們首先要簡要的談談ORACLE的邏輯儲存管理.我們知道,ORACLE在邏輯儲存上分4個粒度:表空間,,區和塊.

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


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

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

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

OK,我們現在回到HWM上來,那麼,什麼是高水位標?這就跟ORACLE的段空間管理相關了.

()ORACLEHWM來界定一個段中使用的塊和未使用的塊.

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

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

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

考慮讓我們看一個段,如一張表,其中填滿了塊,如圖 1 所示。在正常操作過程中,刪除了一些行,如圖 2 所示。現有就有了許多浪費的空間:(I) 在表的上一個末端和現有的塊之間,以及 (II) 在塊內部,其中還有一些沒有刪除的行。  

 

  

" 1:分配給該表的塊。用灰色正方形表示行

ORACLE 不會釋放空間以供其他物件使用,有一條簡單的理由:由於空間是為新插入的行保留的,並且要適應現有行的增長。被佔用的最高空間稱為最高使用標記 (HWM),如圖 2 所示。  

 

  

" 2:行後面的塊已經刪除了;HWM 仍保持不變

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

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

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

所以問題就產生了(一直不解為何ORACLE會採用這種不合理的方式).當使用者發出一個全表掃描時,ORACLE 始終必須從段一直掃描到 HWM,即使它什麼也沒有發現。該任務延長了全表掃描的時間。

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

我們來分析這兩個問題,後者只是帶來空間的浪費,但前者不僅是空間的浪費,而且會帶來嚴重的效能問題.我們來看看下面的例子:

(A)我們先來搭建測試的環境,第一步先建立一個段為手工管理的:

CREATE TABLESPACE "RAINNY"
LOGGING

DATAFILE 'D:ORACLE_HOMEORADATARAINNYRAINNY.ORA' SIZE 5
M
AUTOEXTEND

ON NEXT 10M MAXSIZE UNLIMITED EXTENT MANAGEMENT LOCAL

SEGMENT SPACE MANAGEMENT MANUAL;

(B)建立一個表,注意,此表的第二個欄位我故意設成是CHAR(100),以讓此表在插入1千萬條記錄後,空間有足夠大:

CREATE TABLE TEST_TAB(C1 NUMBER(10),C2 CHAR(100)) TABLESPACE RAINNY;

插入記錄DECLARE
I
NUMBER(10);BEGIN
FOR I IN 1..10000000 LOOP
INSERT INTO TEST_TAB VALUES(I,'TESTSTRING');
END LOOP;
COMMIT;END ;

(C)我們來查詢一下,看在插入一千萬條記錄後所訪問的塊數和查詢所用時間:

SQL> SET TIMING ON

SQL> SET AUTOTRACE TRACEONLY

SQL> SELECT COUNT(*) FROM TEST_TAB;

ELAPSED: 00:01:03.05

EXECUTION PLAN

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

0 SELECT STATEMENT OPTIMIZER=CHOOSE (COST=15056 CARD=1)

1 0 SORT (AGGREGATE)

2 1 TABLE ACCESS (FULL) OF 'TEST_TAB' (COST=15056 CARD=10000

000)

STATISTICS

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

0 RECURSIVE CALLS

0 DB BLOCK GETS

156310 CONSISTENT GETS

154239 PHYSICAL READS

0 REDO SIZE

379 BYTES SENT VIA SQL*NET TO CLIENT

503 BYTES RECEIVED VIA SQL*NET FROM CLIENT

2 SQL*NET ROUNDTRIPS TO/FROM CLIENT

0 SORTS (MEMORY)

0 SORTS (DISK)

1 ROWS PROCESSED

SQL>

我們來看上面的執行計劃,這句SQL總供耗時是:13.訪問方式是採用全表掃描方式(FTS),讀了156310BLOCK,物理讀了154239BLOCK.

我們來分析一下這個表:

BEGIN
DBMS_STATS.GATHER_TABLE_STATS
(OWNNAME=> 'TEST',
TABNAME
=> 'TEST_TAB',

PARTNAME
=> NULL);END;

發現這個表目前使用的BLOCK: 156532,未使用的BLOCK(EMPTY_BLOCKS):0,總行數為(NUM_ROWS):1000 0000

(D)接下來我們把此表的記錄用DELETE方式刪掉,然後再來看看SELECT COUNT(*) FROM TEST_TAB所花的時間:

DELETE FROM TEST_TAB;

COMMIT;

SQL> SELECT COUNT(*) FROM TEST_TAB;

ELAPSED: 00:01:04.03

EXECUTION PLAN

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

0 SELECT STATEMENT OPTIMIZER=CHOOSE (COST=15056 CARD=1)

1 0 SORT (AGGREGATE)

2 1 TABLE ACCESS (FULL) OF 'TEST_TAB' (COST=15056 CARD=1)

STATISTICS

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

0 RECURSIVE CALLS

0 DB BLOCK GETS

156310 CONSISTENT GETS

155565 PHYSICAL READS

0 REDO SIZE

378 BYTES SENT VIA SQL*NET TO CLIENT

503 BYTES RECEIVED VIA SQL*NET FROM CLIENT

2 SQL*NET ROUNDTRIPS TO/FROM CLIENT

0 SORTS (MEMORY)

0 SORTS (DISK)

1 ROWS PROCESSED

SQL>

大家來看,DELETE表後,此時表中已沒有一條記錄,為什麼SELECT COUNT(*) FROM TEST_TAB花的時間為14,

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

相關文章