深入瞭解oracle的高水位(HWM)
(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的段空間管理相關了.
(一)ORACLE用HWM來界定一個段中使用的塊和未使用的塊.
舉個例子來說,當我們建立一個表: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 5M
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總供耗時是:1分3秒.訪問方式是採用全表掃描方式(FTS),邏輯讀了156310個BLOCK,物理讀了154239個BLOCK.
我們來分析一下這個表:
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花的時間為1分4秒,
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/35489/viewspace-84772/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle 高水位(HWM)Oracle
- oracle的高水位線HWMOracle
- oracle的高水位線(HWM)Oracle
- ORACLE 高水位線(HWM)Oracle
- Oracle 高水位(HWM)標記Oracle
- Oracle表段中的高水位線HWMOracle
- Oracle高水位線(HWM)及效能優化Oracle優化
- Oracle案例10——HWM(高水位線)效能優化Oracle優化
- delete與高水位線HWM回收delete
- Oracle段高水位(HWM, high water mark)問題Oracle
- 各個Oracle 版本下如何調整高水位(HWM)Oracle
- Oracle表段中高水位線HWMOracle
- oracle 高水位線詳解Oracle
- oracle11g表的高水位線hwm與dbms_space系列一Oracle
- Oracle高水位Oracle
- 一、oracle 高水位線詳解Oracle
- 【實驗】關於HWM(高水位)的學習與測試
- oracle 高水位線及如何有效的降低高水位線Oracle
- oracle回收高水位Oracle
- oracle 回收高水位線Oracle
- Oracle 降低高水位線Oracle
- oracle回收高水位線Oracle
- oracle高水位問題Oracle
- 降低Oracle高水位線的方法Oracle
- Oracle的高水位線介紹Oracle
- 通過降低表的高水位(HWM: High Water Mark) ,解決一生產系統故障
- oracle高水位線處理Oracle
- oracle 高水位分析處理Oracle
- Oracle之降低高水位線Oracle
- ORACLE的簡單處理高水位Oracle
- Oracle 高水位線的一點研究Oracle
- ORACLE高水位表的查詢方法Oracle
- 深入瞭解ORACLE的邏輯讀Oracle
- 對Oracle高水位線的研究實踐Oracle
- Oracle 找出需要回收高水位的表Oracle
- 轉載 :深入瞭解ORACLE SCNOracle
- 深入瞭解Oracle資料字典Oracle
- oracle表碎片以及整理(高水位線)Oracle