來源: ?http://www.cnblogs.com/linjiqin/archive/2012/01/15/2323030.html
一、oracle 高水位線詳解
一、什么是水線(High Water Mark)?
所有的oracle段(segments,在此,為了理解方便,建議把segment作為表的一個(gè)同義詞) 都有一個(gè)在段內(nèi)容納數(shù)據(jù)的上限,我們把這個(gè)上限稱為"high water mark"或HWM。 這個(gè)HWM是一個(gè)標(biāo)記,用來說明已經(jīng)有多少?zèng)]有使用的數(shù)據(jù)塊分配給這個(gè)segment。HWM通常增長(zhǎng)的幅度為一次5個(gè)數(shù)據(jù)塊,原則上HWM只會(huì)增大,不會(huì)縮小,即使將表中的數(shù)據(jù)全部刪除,HWM還是為原值,由于這個(gè)特點(diǎn),使HWM很象一個(gè)水庫(kù)的歷史最高水位,這也就是HWM的原始含義,當(dāng)然不能說一個(gè)水庫(kù)沒水了,就說該水庫(kù)的歷史最高水位為0。但是如果我們?cè)诒砩鲜褂昧藅runcate命令,則該表的HWM會(huì)被重新置為0。
???????????
二、HWM數(shù)據(jù)庫(kù)的操作有如下影響:
a) 全表掃描通常要讀出直到HWM標(biāo)記的所有的屬于該表數(shù)據(jù)庫(kù)塊,即使該表中沒有任何數(shù)據(jù)。
b) 即使HWM以下有空閑的數(shù)據(jù)庫(kù)塊,鍵入在插入數(shù)據(jù)時(shí)使用了append關(guān)鍵字,則在插入時(shí)使用HWM以上的數(shù)據(jù)塊,此時(shí)HWM會(huì)自動(dòng)增大。
???????????????
三、如何知道一個(gè)表的HWM?
a) 首先對(duì)表進(jìn)行分析:
ANALYZE TABLE <tablename> ESTIMATE/COMPUTE STATISTICS;
b) SELECT blocks, empty_blocks, num_rows
FROM user_tables
WHERE table_name = <tablename>;
說明:
BLOCKS 列代表該表中 曾經(jīng) 使用過得數(shù)據(jù)庫(kù)塊的數(shù)目,即水線。
EMPTY_BLOCKS 代表分配給該表,但是在水線以上的數(shù)據(jù)庫(kù)塊,即從來沒有使用的數(shù)據(jù)塊。
????????????
讓我們以一個(gè)有28672行的BIG_EMP1表為例進(jìn)行說明:
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個(gè)數(shù)據(jù)庫(kù)塊,這是因?yàn)橛幸粋€(gè)數(shù)據(jù)庫(kù)塊被保留用作segment header。DBA_SEGMENTS.BLOCKS 表示分配給這個(gè)表的所有的數(shù)據(jù)庫(kù)塊的數(shù)目。USER_TABLES.BLOCKS表示已經(jīng)使用過的數(shù)據(jù)庫(kù)塊的數(shù)目。
?????????????
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 ----這表名沒有任何數(shù)據(jù)庫(kù)塊容納數(shù)據(jù),即表中無數(shù)據(jù)
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命令產(chǎn)生的空閑空間,注意該表分配的空間由原先的1024塊降為512塊。
為了保留由delete命令產(chǎn)生的空閑空間,可以使用 TRUNCATE TABLE big_emp1 REUSE STORAGE.
用此命令后,該表還會(huì)是原先的1024塊。
???????? ????????
四、Oracle表段中的高水位線HWM
在Oracle數(shù)據(jù)的存儲(chǔ)中,可以把存儲(chǔ)空間想象為一個(gè)水庫(kù),數(shù)據(jù)想象為水庫(kù)中的水。水庫(kù)中的水的位置有一條線叫做水位線,在Oracle中,這條線被稱為高水位線(High-warter mark, HWM)。在數(shù)據(jù)庫(kù)表剛建立的時(shí)候,由于沒有任何數(shù)據(jù),所以這個(gè)時(shí)候水位線是空的,也就是說HWM為最低值。當(dāng)插入了數(shù)據(jù)以后,高水位線就會(huì)上漲,但是這里也有一個(gè)特性,就是如果你采用delete語句刪除數(shù)據(jù)的話,數(shù)據(jù)雖然被刪除了,但是高水位線卻沒有降低,還是你剛才刪除數(shù)據(jù)以前那么高的水位。 也就是說,這條高水位線在日常的增刪操作中只會(huì)上漲,不會(huì)下跌。
??????????????
下面我們來談一下Oracle中Select語句的特性。Select語句會(huì)對(duì)表中的數(shù)據(jù)進(jìn)行一次掃描,但是究竟掃描多少數(shù)據(jù)存儲(chǔ)塊呢,這個(gè)并不是說數(shù)據(jù)庫(kù)中有多少數(shù)據(jù),Oracle就掃描這么大的數(shù)據(jù)塊, 而是Oracle會(huì)掃描高水位線以下的數(shù)據(jù)塊。 現(xiàn)在來想象一下,如果剛才是一張剛剛建立的空表,你進(jìn)行了一次Select操作,那么由于高水位線HWM在最低的0位置上,所以沒有數(shù)據(jù)塊需要被掃描,掃描時(shí)間會(huì)極短。而如果這個(gè)時(shí)候你首先插入了一千萬條數(shù)據(jù),然后再用delete語句刪除這一千萬條數(shù)據(jù)。由于插入了一千萬條數(shù)據(jù),所以這個(gè)時(shí)候的高水位線就在一千萬條數(shù)據(jù)這里。后來刪除這一千萬條數(shù)據(jù)的時(shí)候,由于delete語句不影響高水位線,所以高水位線依然在一千萬條數(shù)據(jù)這里。這個(gè)時(shí)候再一次用select語句進(jìn)行掃描,雖然這個(gè)時(shí)候表中沒有數(shù)據(jù),但是由于掃描是按照高水位線來的,所以需要把一千萬條數(shù)據(jù)的存儲(chǔ)空間都要掃描一次,也就是說這次掃描所需要的時(shí)間和掃描一千萬條數(shù)據(jù)所需要的時(shí)間是一樣多的。 所以有時(shí)候有人總是經(jīng)常說,怎么我的表中沒有幾條數(shù)據(jù),但是還是這么慢呢,這個(gè)時(shí)候其實(shí)奧秘就是這里的高水位線了。
????????????????
那有沒有辦法讓高水位線下降呢,其實(shí)有一種比較簡(jiǎn)單的方法,那就是采用TRUNCATE語句進(jìn)行刪除數(shù)據(jù)。采用TRUNCATE語句刪除一個(gè)表的數(shù)據(jù)的時(shí)候,類似于重新建立了表,不僅把數(shù)據(jù)都刪除了,還把HWM給清空恢復(fù)為0。 所以如果需要把表清空,在有可能利用TRUNCATE語句來刪除數(shù)據(jù)的時(shí)候就利用TRUNCATE語句來刪除表,特別是那種數(shù)據(jù)量有可能很大的臨時(shí)存儲(chǔ)表。
?????????????
在手動(dòng) 段空間管理 (Manual Segment Space Management)中,段中只有一個(gè)HWM,但是在Oracle9iRelease1才添加的自動(dòng)段空間管理(Automatic Segment Space Management)中,又有了一個(gè)低HWM的概念出來。為什么有了HWM還又有一個(gè)低HWM呢,這個(gè)是因?yàn)樽詣?dòng)段空間管理的特性造成的。在手段段空間管理中,當(dāng)數(shù)據(jù)插入以后,如果是插入到新的數(shù)據(jù)塊中,數(shù)據(jù)塊就會(huì)被自動(dòng)格式化等待數(shù)據(jù)訪問。而在自動(dòng)段空間管理中,數(shù)據(jù)插入到新的數(shù)據(jù)塊以后,數(shù)據(jù)塊并沒有被格式化,而是在第一次在第一次訪問這個(gè)數(shù)據(jù)塊的時(shí)候才格式化這個(gè)塊。 所以我們又需要一條水位線,用來標(biāo)示已經(jīng)被格式化的塊。這條水位線就叫做低HWM。一般來說,低HWM肯定是低于等于HWM的。
??????????????? ??
五、修正ORACLE表的高水位線
在ORACLE中,執(zhí)行對(duì)表的刪除操作不會(huì)降低該表的高水位線。而全表掃描將始終讀取一個(gè)段(segment)中所有低于高水位線標(biāo)記的塊。如果在執(zhí)行刪除操作后不降低高水位線標(biāo)記,則將導(dǎo)致查詢語句的性能低下。下面的方法都可以降低高水位線標(biāo)記。
1.執(zhí)行表重建指令 alter table table_name move;
(在線轉(zhuǎn)移表空間ALTER TABLE 。。。 MOVE TABLESPACE 。。。 ALTER TABLE 。。。 MOVE 后面不跟參數(shù)也行, 不跟參數(shù)表還是在原來的表空間,move后記住重建索引 。如果以后還要繼續(xù)向這個(gè)表增加數(shù)據(jù),沒有必要move, 只是釋放出來的空間,只能這個(gè)表用,其他的表或者segment無法使用該空間 )
2.執(zhí)行alter table table_name shrink space; 注意,此命令為Oracle 10g新增功能,再執(zhí)行該指令之前必須允許行移動(dòng)alter table table_name enable row movement;
3.復(fù)制要保留的數(shù)據(jù)到臨時(shí)表t,drop原表,然后rename臨時(shí)表t為原表
4.emp/imp
5.alter?? table? table_name? deallocate?? unused??
6.盡量truncate吧
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
