日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Oracle-HWM(High Water Mark) 高水位解读

發(fā)布時間:2025/3/21 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle-HWM(High Water Mark) 高水位解读 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

讀前須知:Oracle的邏輯存儲管理


ORACLE在邏輯存儲上分4個粒度 ,由大到小為: 表空間, 段, 區(qū) 和 塊.


塊Block

塊:是粒度最小的存儲單位,現(xiàn)在標(biāo)準(zhǔn)的塊大小是8K,ORACLE每一次I/O操作也是按塊來操作的,也就是說當(dāng)ORACLE從數(shù)據(jù)文件讀數(shù)據(jù)時,是讀取多少個塊,而不是多少行. 每一個Block里可以包含多個row.

數(shù)據(jù)塊的大小是通過kb字節(jié)個數(shù)來指定的,默認為8KB。相關(guān)參數(shù)為db_block_size

SQL> show parameter db_block_sizeNAME TYPE VALUE ----------------------- --------------------- --------- db_block_size integer 8192

區(qū)Extent

由一系列相鄰的塊而組成,這也是ORACLE空間分配的基本單位.

區(qū)extent是比數(shù)據(jù)塊大一級的存儲結(jié)構(gòu),表示的是一連串連續(xù)的數(shù)據(jù)塊集合。

在進行存儲數(shù)據(jù)信息的時候,Oracle將分配數(shù)據(jù)塊進行存儲,但是不能保證所有分配的數(shù)據(jù)塊都是連續(xù)的結(jié)構(gòu)。

所以,出現(xiàn)分區(qū)extent的概念,表示一系列連續(xù)的數(shù)據(jù)塊集合。

舉個例子來說,當(dāng)我們創(chuàng)建一個表時,首先ORACLE會分配一區(qū)的空間給這個表,隨著數(shù)據(jù)不斷地增長,原來的這個區(qū)容不下插入的數(shù)據(jù)時,ORACLE是以區(qū)為單位進行擴展的,也就是說再分配多少個區(qū)給這個表,而不是多少個塊.

視圖dba_extents(或者all_extents、user_extents)是我們研究分區(qū)結(jié)構(gòu)和存儲構(gòu)成的重要手段。


段Segment

段: 是由一系列的區(qū)extent所組成

數(shù)據(jù)段是與數(shù)據(jù)庫對象相對應(yīng),一般一個數(shù)據(jù)庫對象對應(yīng)一個數(shù)據(jù)段。

多個extent是對應(yīng)一個數(shù)據(jù)段,每個數(shù)據(jù)段實際上就是數(shù)據(jù)庫一個對象的代表。

一般來說, 當(dāng)創(chuàng)建一個對象時(表,索引),就會分配一個段給這個對象.

從dba_segments、user_segments視圖中,可以比較清楚看清數(shù)據(jù)段的結(jié)構(gòu)。


表空間Tablespace

TableSpace是存儲結(jié)構(gòu)中的最高層結(jié)構(gòu)。建立一個表空間的時候,是需要指定存儲的文件。一個表空間可以指定多個數(shù)據(jù)文件,多個文件可以在不同的物理存儲上。也就是說,表空間是可以跨物理存儲的。

但是有一點就是,表空間下一級對象數(shù)據(jù)段的存儲,是不能指定存儲在那個文件里的。所以,要想讓數(shù)據(jù)對象訪問IO負載均衡,需要指定不同的數(shù)據(jù)對象在不同的表空間里。這也就是為什么將數(shù)據(jù)表和索引建立在不同的表空間的原因。

表空間通過v$tablespace進行訪問

其中兩個參數(shù)需要注意一下。

一個是bigfile,是一個標(biāo)志位,標(biāo)志表空間是不是所謂的大文件表空間。

大文件表空間是在10g中推出的一個新特性,處于性能考慮,可以設(shè)置表空間為大文件表空間,存儲超過百T的數(shù)據(jù),但是要求數(shù)據(jù)文件只能有一個。

另一個是flashback_on,表示表空間的閃回特性是否開啟。

還有 dba_tablespaces 、 user_tablespaces。


Oracle表段中的高水位線HWM

在數(shù)據(jù)庫表剛建立的時候,由于沒有任何數(shù)據(jù),所以這個時候水位線是空的,也就是說HWM為最低值。

當(dāng)插入了數(shù)據(jù)以后,高水位線就會上漲,但如果你采用delete語句刪除數(shù)據(jù)的話,數(shù)據(jù)雖然被刪除了,但是高水位線卻沒有降低,還是你剛才刪除數(shù)據(jù)以前那么高的水位。

也就是說,這條高水位線在日常的增刪操作中只會上漲,不會下跌。

HWM通常增長的幅度為一次5個數(shù)據(jù)塊.

Select語句會對表中的數(shù)據(jù)進行一次掃描,但是究竟掃描多少數(shù)據(jù)存儲塊呢,這個并不是說數(shù)據(jù)庫中有多少數(shù)據(jù),Oracle就掃描這么大的數(shù)據(jù)塊,而是Oracle會掃描高水位線以下的數(shù)據(jù)塊。

試想一下,新建的一個空表,Select一下,由于高水位線HWM在最低的0位置上,所以沒有數(shù)據(jù)塊需要被掃描,掃描時間會極短。

如果這個時候你首先插入了一千萬條數(shù)據(jù),然后再用delete語句刪除這一千萬條數(shù)據(jù)。由于插入了一千萬條數(shù)據(jù),所以這個時候的高水位線就在一千萬條數(shù)據(jù)這里。后來刪除這一千萬條數(shù)據(jù)的時候,由于delete語句不影響高水位線,所以高水位線依然在一千萬條數(shù)據(jù)這里。

這個時候再一次用select語句進行掃描,雖然這個時候表中沒有數(shù)據(jù),但是由于掃描是按照高水位線來的,所以需要把一千萬條數(shù)據(jù)的存儲空間都要掃描一次,也就是說這次掃描所需要的時間和掃描一千萬條數(shù)據(jù)所需要的時間是一樣多的。所以有時候有人總是經(jīng)常說,怎么我的表中沒有幾條數(shù)據(jù),但是還是這么慢呢,這個時候其實奧秘就是這里的高水位線了。

那有沒有辦法讓高水位線下降呢 ? 采用TRUNCATE語句刪除一個表的數(shù)據(jù)的時候,類似于重新建立了表,不僅把數(shù)據(jù)都刪除了,還把HWM給清空恢復(fù)為0。

所以如果需要把表清空,在有可能利用TRUNCATE語句來刪除數(shù)據(jù)的時候就利用TRUNCATE語句來刪除表,特別是那種數(shù)據(jù)量有可能很大的臨時存儲表。


在手動段空間管理(Manual Segment Space Management)中,段中只有一個HWM,

但是在Oracle 9i Release1才添加的自動段空間管理(Automatic Segment Space Management)中,又有了一個低HWM的概念出來。

為什么有了HWM還又有一個低HWM呢,這個是因為自動段空間管理的特性造成的。在手段段空間管理中,當(dāng)數(shù)據(jù)插入以后,如果是插入到新的數(shù)據(jù)塊中,數(shù)據(jù)塊就會被自動格式化等待數(shù)據(jù)訪問。

而在自動段空間管理中,數(shù)據(jù)插入到新的數(shù)據(jù)塊以后,數(shù)據(jù)塊并沒有被格式化,而是在第一次訪問這個數(shù)據(jù)塊的時候才格式化這個塊。

所以我們又需要一條水位線,用來標(biāo)示已經(jīng)被格式化的塊。這條水位線就叫做低HWM。一般來說,低HWM肯定是低于等于HWM的。


降低ORACLE表的高水位線

在ORACLE中,執(zhí)行對表的刪除操作不會降低該表的高水位線。而全表掃描將始終讀取一個段(extent)中所有低于高水位線標(biāo)記的塊。如果在執(zhí)行刪除操作后不降低高水位線標(biāo)記,則將導(dǎo)致查詢語句的性能低下。

rebuild, truncate, shrink,move 等操作會降低高水位。

執(zhí)行表重建指令 alter table table_name move

在線轉(zhuǎn)移表空間ALTER TABLE … MOVE TABLESPACE ..

當(dāng)你創(chuàng)建了一個對象如表以后,不管你有沒有插入數(shù)據(jù),它都會占用一些塊,ORACLE也會給它分配必要的空間.

同樣,用ALTER TABLE MOVE釋放自由空間后,還是保留了一些空間給這個表.

ALTER TABLE … MOVE 后面不跟參數(shù)也行,不跟參數(shù)表還是在原來的表空間,Move后記住重建索引.

如果以后還要繼續(xù)向這個表增加數(shù)據(jù),沒有必要move, 只是釋放出來的空間,只能這個表用,其他的表或者segment無法使用該空間。


執(zhí)行alter table table_name shrink space-10g新功能

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

如果要同時壓縮表的索引,可以發(fā)布:alter table test_tab shrink space cascade


重建表

復(fù)制要保留的數(shù)據(jù)到臨時表t,drop原表,然后rename臨時表t為原表


用邏輯導(dǎo)入導(dǎo)出: Emp/Imp


Alter table table_name deallocate unused

DEALLOCATE UNUSED會釋放HWM上面的未使用空間,但是并不會釋放HWM下面的自由空間,也不會移動HWM的位置.


truncate(推薦使用)

truncate table xxx


HWM的特征

ORACLE用HWM來界定一個段中使用的塊和未使用的塊

當(dāng)我們創(chuàng)建一個表時,ORACLE就會為這個對象分配一個段.在這個段中,即使我們未插入任何記錄,也至少有一個區(qū)被分配,第一個區(qū)的第一個塊就稱為段頭(SEGMENT HEADE),段頭中就儲存了一些信息,HWM的信息就存儲在此.

我們不斷插入數(shù)據(jù)時,HWM會往不斷上移,這樣,在HWM之下的,就表示使用過的塊,HWM之上的就表示已分配但從未使用過的塊.


HWM在插入數(shù)據(jù)時,當(dāng)現(xiàn)有空間不足而進行空間的擴展時會向上移,但刪除數(shù)據(jù)時不會往下移.

ORACLE 不會釋放空間以供其他對象使用,有一條簡單的理由:由于空間是為新插入的行保留的,并且要適應(yīng)現(xiàn)有行的增長。被占用的最高空間稱為最高使用標(biāo)記 (HWM).


HWM的信息存儲在段頭當(dāng)中.

HWM本身的信息是儲存在段頭.

在段空間是手工管理方式時,ORACLE是通過FREELIST(一個單向鏈表)來管理段內(nèi)的空間分配.

在段空間是自動管理方式時(ASSM),ORACLE是通過BITMAP來管理段內(nèi)的空間分配.


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

所以問題就產(chǎn)生了.當(dāng)用戶發(fā)出一個全表掃描時,ORACLE 始終必須從段一直掃描到 HWM,即使它什么也沒有發(fā)現(xiàn)。

該任務(wù)延長了全表掃描的時間。


當(dāng)用直接路徑插入行時,即使HWM以下有空閑的數(shù)據(jù)庫塊,鍵入在插入數(shù)據(jù)時使用了append關(guān)鍵字,則在插入時使用HWM以上的數(shù)據(jù)塊,此時HWM會自動增大。

例如,通過直接加載插入(用 APPEND 提示插入)或通過 SQL*LOADER 直接路徑 數(shù)據(jù)塊直接置于 HWM 之上。它下面的空間就浪費掉了。


栗子

數(shù)據(jù)庫版本 Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.4.0

創(chuàng)建測試表

SQL> create table tt(id number);Table created

此時表沒有分析,是原始的數(shù)據(jù),即8個數(shù)據(jù)塊。

--空的 SQL> SELECT segment_name,segment_type,blocks FROM dba_segments a WHERE a.segment_name = 'TT';SEGMENT_NAME SEGMENT_TYPE BLOCKS -------------------------------------------------------------------------------- ------------------ ------------空的 SQL> SELECT table_name,num_rows,blocks,empty_blocks FROM user_tables WHERE table_name='TT';TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS ------------------------------ ---------- ---------- ------------ TT

向表中插入一些測試數(shù)據(jù)

SQL> declare2 i number;3 begin4 for i in 1 .. 10000 loop5 insert into tt values (i);6 end loop;7 commit;8 end;9 /PL/SQL procedure successfully completed

重新查詢表的信息

此時表TT 占用的塊已經(jīng)是24個了.

但是user_tables 顯示的信息還是為空。 因為沒有做統(tǒng)計分析。

收集統(tǒng)計信息

SQL> exec DBMS_STATS.GATHER_TABLE_STATS(user,'TT');PL/SQL procedure successfully completed

再此查詢一下

此時user_tables 已經(jīng)有了數(shù)據(jù),顯示的使用了20個數(shù)據(jù)塊。 但是empty_blocks 還是為空。 這里要注意的地方。 empty_blocks 這個字段只有使用analyze 收集統(tǒng)計信息之后才會有數(shù)據(jù)。


使用analyze搜集統(tǒng)計信息

SQL> analyze table tt compute statistics;Table analyzed

delete 數(shù)據(jù),不會降低高水位

可以發(fā)現(xiàn) 分析前后,blocks 和 empty_blocks 都沒有發(fā)生變化。


truncate 表,可以降低高水位

--truncate 表 SQL> truncate table tt;Table truncated--查詢段信息,blocks由24降到了8 SQL> SELECT segment_name,segment_type,blocks FROM dba_segments WHERE segment_name='TT';SEGMENT_NAME SEGMENT_TYPE BLOCKS --------- ---------- ---------- TT TABLE 8--查詢表信息,沒有改變 SQL> SELECT table_name,num_rows,blocks,empty_blocks FROM user_tables WHERE table_name='TT';TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS -------- ---------- ------ ------ TT 0 20 4------------------------------------------------------------ ------------------------------------------------------------ --收集下表信息 SQL> exec dbms_stats.gather_table_stats(user,'TT');PL/SQL procedure successfully completed--重新統(tǒng)計下段信息,一樣 SQL> SELECT segment_name,segment_type,blocks FROM dba_segments WHERE segment_name='TT';SEGMENT_NAME SEGMENT_TYPE BLOCKS --------- ---------- ---------- TT TABLE 8--重新查詢表信息 BLOCKS20降為0, 但是empyt_blocks 還是4SQL> SELECT table_name,num_rows,blocks,empty_blocks FROM user_tables WHERE table_name='TT';TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS ---------- ----- ---------- ------------ TT 0 0 4--analyze 分析下 更改EMPTY_BLOCKS的值 SQL> analyze table tt compute statistics;Table analyzed--重新查詢段信息, SQL> SELECT segment_name,segment_type,blocks FROM dba_segments WHERE segment_name='TT';SEGMENT_NAME SEGMENT_TYPE BLOCKS --------- ---------- ---------- TT TABLE 8--重新查詢表信息 SQL> SELECT table_name,num_rows,blocks,empty_blocks FROM user_tables WHERE table_name='TT';TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS ---------- ----- ---------- ------------ TT 0 0 8SQL>

總共8個數(shù)據(jù)塊,8個為空


Alter table move 和Shrink的區(qū)別

Shrink

在10g之后,整理碎片消除行遷移的新增功能shrink space

語法

alter table <table_name> shrink space [ <null> | compact | cascade ];
  • compact: 這個參數(shù)當(dāng)系統(tǒng)的負載比較大時可以用,不降低HWM。如果系統(tǒng)負載較低時,直接用alter table table_name shrink space就一步到位了
  • cascade:這個參數(shù)是在shrink table的時候自動級聯(lián)索引,相當(dāng)于rebulid index。

基于普通表

--shrink必須開啟行遷移功能。 alter table table_name enable row movement ;--保持HWM,相當(dāng)于把塊中數(shù)據(jù)打結(jié)實了 alter table table_name shrink space compact;--回縮表與降低HWM alter table table_name shrink space;--回縮表與相關(guān)索引,降低HWM alter table table_name shrink space cascade;--回縮索引與降低HWM alter index index_name shrink space

雖然在10g中可以用shrink ,但也有些限制:

  • 1). 對cluster,cluster table,或具有Long,lob類型列的對象 不起作用。
  • 2). 不支持具有function-based indexes 或 bitmap join indexes的表
  • 3). 不支持mapping 表或index-organized表。
  • 4). 不支持compressed 表

shrink栗子

SQL> create table tt(id number);SQL> declarei number; beginfor i in 1 .. 10000 loopinsert into tt values (i);end loop;commit; end;SQL> exec DBMS_STATS.GATHER_TABLE_STATS(user,'TT');SQL> analyze table tt compute statistics;SQL> delete from tt;SQL> commit ;SQL> alter table tt enable row movement ; SQL> alter table tt shrink space; SQL> analyze table tt compute statistics;SQL> SELECT segment_name,segment_type,blocks FROM dba_segments WHERE segment_name='TT';SQL> SELECT table_name,num_rows,blocks,empty_blocks FROM user_tables WHERE table_name='TT';


Move

通過desc table_name 來檢查表中是否有LOB 字段,

表中沒有l(wèi)ob字段

如果表沒有LOB字段, 直接 alter table move; 然后 rebuild index

表中包含了LOB字段

alter table owner.table_name move tablespace tablespace_name lob (lob_column) store as lobsegment tablespace tablespace_name;

也可以單獨move lob,但是表上的index 同樣會失效. 所以在操作結(jié)束,需要對索引進行rebuild。

alter table owner.table_name move lob(lob_column) store as lobsegment tablespace tablespace_name ;

索引的rebuild:

首先用下面的SQL查看表上面有哪類索引:

SELECT a.owner,a.index_name,a.index_type,a.partitioned,a.status,b.status p_status,b.compositeFROM dba_indexes aLEFT JOINdba_ind_partitions bON a.owner = b.index_owner AND a.index_name = b.index_nameWHERE a.owner = '&owner' AND a.table_name = '&table_name';

對于普通索引直接rebuild online nologging parallel,
對于分區(qū)索引,必須單獨rebuild 每個分區(qū),
對于組合分區(qū)索引,必須單獨rebuild 每個子分區(qū)。


總結(jié)

Move 通過移動數(shù)據(jù)來來降低HWM,因此需要更多的磁盤空間。
Shrink 通過delete 和 insert, 會產(chǎn)生較多的undo 和redo。

shrink space收縮到數(shù)據(jù)存儲的最小值,alter table move(不帶參數(shù))收縮到initial指定值,也可以用alter table test move storage(initial 500k)指定收縮的大小,這樣可以達到shrink space效果。

總之,使用Move 效率會高點,但是會導(dǎo)致索引失效。Shrink 會產(chǎn)生undo 和redo,速度相對也慢一點。


博文學(xué)習(xí)至David Dai 大神,再此向大神致敬!

總結(jié)

以上是生活随笔為你收集整理的Oracle-HWM(High Water Mark) 高水位解读的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。