oracle高水位线
| ?ORACLE在邏輯存儲上分4個粒度:?表空間,?段,?區(qū)?和?塊. ? ??????1.1?塊:?是粒度最小的存儲單位,現(xiàn)在標(biāo)準(zhǔn)的塊大小是8K,ORACLE每一次I/O操作也是按塊來操作的,也就是說當(dāng)ORACLE從數(shù)據(jù)文件讀數(shù)據(jù)時,是讀取多少個塊,而不是多少行.??每一個Block里可以包含多個row. ? ???????1.2?區(qū):?由一系列相鄰的塊而組成,這也是ORACLE空間分配的基本單位,舉個例子來說,當(dāng)我們創(chuàng)建一個表Dave時,首先ORACLE會分配一區(qū)的空間給這個表,隨著不斷的INSERT數(shù)據(jù)到Dave,原來的這個區(qū)容不下插入的數(shù)據(jù)時,ORACLE是以區(qū)為單位進(jìn)行擴(kuò)展的,也就是說再分配多少個區(qū)給Dave,而不是多少個塊. ? ???????1.3?段:?是由一系列的區(qū)所組成,?一般來說,?當(dāng)創(chuàng)建一個對象時(表,索引),就會分配一個段給這個對象.?所以從某種意義上來說,段就是某種特定的數(shù)據(jù).如CREATE TABLE Dave,這個段就是數(shù)據(jù)段,而CREATE INDEX ON Dave(NAME), ORACLE同樣會分配一個段給這個索引,但這是一個索引段了.查詢段的信息可以通過數(shù)據(jù)字典: SELECT * FROM USER_SEGMENTS來獲得. ? ???????1.4?表空間:?包含段,區(qū)及塊.表空間的數(shù)據(jù)物理上儲存在其所在的數(shù)據(jù)文件中.一個數(shù)據(jù)庫至少要有一個表空間 | ||
| ORACLE用HWM來界定一個段中使用的塊和未使用的塊。由于空間是為新插入的行保留的,并且要適應(yīng)現(xiàn)有行的增長。被占用的最高空間稱為最高使用標(biāo)記?(HWM) ? ? ? ? ?1.當(dāng)我們創(chuàng)建一個表時, ORACLE就會為這個對象分配一個段, 在這個段中即使我們未插入任何記錄, 也至少有一個區(qū)被分配, 第一 ? ? ? ? ? ? ?個區(qū)的第一個塊就稱為段頭塊(SEGMENT_HEADER), 段頭中就儲存了一些信息, 其中HWM的信息就存儲在此。 ? ? ? ? ? ?此時, 因?yàn)榈谝?個區(qū)的第一塊用于存儲段頭的一些信息, 雖然沒有存儲任何實(shí)際的記錄, 但也算是被使用, 此時HWM是位于第2個 ? ? ? ? ? ? ?塊, 當(dāng)我們不斷插入數(shù)據(jù)后, 第一個塊已經(jīng)放不下后面新插入的數(shù)據(jù), 此時, ORACLE將高水位之上的塊用于存儲新增數(shù)據(jù), 同時, ? ? ? ? ? ? HWM本身也向上移, 也就是說, 當(dāng)我們不斷插入數(shù)據(jù)時, HWM會不斷上移, 這樣, 在HWM之下的, 就表示使用過的塊。 HWM之上 ? ? ? ? ? ? 的就表示已分配但從未使用過的塊。 ????????2 .HWM在插入數(shù)據(jù)時, 當(dāng)現(xiàn)有空間不足而進(jìn)行空間的擴(kuò)展時會向上移, 但刪除數(shù)據(jù)時不會往下移。 ? ? ? ??3 .HWM本身的信息是存儲在段頭?: ? ? ? ? ? ? ? ? ? 在段空間是手工管理方式時, ORACLE是通過FREELIST(一個單向鏈表)來管理段內(nèi)的空間分配, ? ? ? ? ? ? ? ? ? 在段空間是自動管理方式時, ORACLE是通過BITMAP來管理段內(nèi)的空間分配。 ????????4 .ORACLE的全表掃描是讀取高水位標(biāo)記(HWM)以下的所有塊。 ? ? ? ? 5.HWM通常增長的幅度為一次5個數(shù)據(jù)塊,原則上HWM只會增大,不會縮小,即使將表中的數(shù)據(jù)全部刪除,HWM還是為原值,但 ? ? ? ? ? ?是如果我們在表上使用了truncate命令,則該表的HWM會被重新置為0,這條高水位線在日常的增刪操作中只會上漲,不會下跌 ?所以問題就產(chǎn)生了, 當(dāng)用戶發(fā)出一個全表掃描時, ORACLE始終必須從段一直掃描到HWM, 即使它什么也沒有發(fā)現(xiàn)。 該任務(wù)延長了全表 ?掃描的時間。 | ||
| 低HWM: ??? 在管理段的時候通常有兩種方法:手動管理段空間(Manual Segment Space Management )和自動段空間(Automatic Segment Space Management) 在手動段空間管理(Manual Segment Space Management)中,段中只有一個HWM,但是在Oracle 9i Release1才添加的自動段空間管理(Automatic Segment Space Management)中,又有了一個低HWM的概念出來。為什么有了HWM還又有一個低HWM呢,這個是因?yàn)樽詣佣慰臻g管理的特性造成的。 在手段段空間管理中,當(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的。 | ||
| HWM數(shù)據(jù)庫的操作有如下影響: a) 全表掃描通常要讀出直到HWM標(biāo)記的所有的屬于該表數(shù)據(jù)庫塊,即使該表中沒有任何數(shù)據(jù)。 b) 即使HWM以下有空閑的數(shù)據(jù)庫塊,鍵入在插入數(shù)據(jù)時使用了append關(guān)鍵字,則在插入時使用HWM以上的數(shù)據(jù)塊,此時HWM會自動增大。 | ||
| 使用delete不能使高水位線降低,使用truncate可以使用高水位線降低,所以當(dāng)刪除整表數(shù)據(jù)或者分區(qū)最好是用truncate, ? TRUNCATE命令回收了由delete命令產(chǎn)生的空閑空間為了保留由delete命令產(chǎn)生的空閑空間,可以使用TRUNCATE TABLE 55LINUX REUSE STORAGE.用此命令后,該表還會是原先的1024塊 ? 采用TRUNCATE語句刪除一個表的數(shù)據(jù)的時候,類似于重新建立了表,不僅把數(shù)據(jù)都刪除了,還把HWM給清空恢復(fù)為0。所以如果需要把表清空,在有可能利用TRUNCATE語句來刪除數(shù)據(jù)的時候就利用TRUNCATE語句來刪除表,特別是那種數(shù)據(jù)量有可能很大的臨時存儲表。 | ||
| 在9i的時候,一個很成熟的碎片整理技術(shù)。 整理表碎片通常的方法是move表 高水位以下合并碎片,不移動高水位 當(dāng)然move是不能在線進(jìn)行的, 不跟參數(shù)表還是在原來的表空間 而且move后相應(yīng)的索引也會失效,需要重建 如果以后還要繼續(xù)向這個表增加數(shù)據(jù),沒有必要move,只是釋放出來的空間,只能這個表用,其他的表或者segment無法使用該空間 | table在進(jìn)行move操作時,我們只能對它進(jìn)行select的操作,DML會全部阻塞(move生成的undo和redo是非常少的)。反過來說,當(dāng)我們的一個session對table進(jìn)行DML操作且沒有commit時,? | ? |
| ? ? ?oracle在10g時候提供了shrink space碎片整理功能,不僅能整理碎片還可以收縮高水位,索引也不需要重建。 shrink的一個優(yōu)點(diǎn)是能在線進(jìn)行,不影響表上的DML操作,當(dāng)然,并發(fā)的DML操作在shrink結(jié)束的時刻會出現(xiàn)短暫的block;? ? SHRINK(收縮) TABLE(表空間收縮) 實(shí)質(zhì)上構(gòu)造一個新表(在內(nèi)部表現(xiàn)為一系列的DML操作,即將副本插入新位置,刪除原來位置的記錄)靠近末尾處(右端)數(shù)據(jù)塊中的記錄往開始處(左端)的空閑空間處移動(DML操作),不會引起DML觸發(fā)器當(dāng)所有可能的移動被完成,高水位線將會往左端移動(DDL操作),新的高水位線右邊的空閑空間被釋放(DDL操作) ???? ???從10g開始, ORACLE開始提供SHRINK的命令, 假如我們的表空間中支持自動段空間管理(ASSM), 就可以使用這個特性縮小段, 即降低HWM。 10g的這個新特性,?必須啟用行記錄轉(zhuǎn)移(enable row movement)僅僅適用于堆表,且位于自動段空間管理的表空間(堆表包括:標(biāo)準(zhǔn)表,分區(qū)表,物化視圖容器,物化視圖日志表) ???????如果經(jīng)常在表上執(zhí)行DML操作, 會造成數(shù)據(jù)庫塊中數(shù)據(jù)分布稀疏, 浪費(fèi)大量空間。 同時也會影響權(quán)標(biāo)掃描的性能。 因?yàn)槿頀呙栊枰L問更多的數(shù)據(jù)塊。從oracle10g開始, 表可以通過SHRINK來重組數(shù)據(jù)使數(shù)據(jù)分布更緊密, 同時降低HWM釋放空閑數(shù)據(jù)塊。??????? | shrink必須開啟行遷移功能。 segment shrink分為兩個階段: 1 數(shù)據(jù)重組(compact): 執(zhí)行ALTER TABLE test SHRINK SPACE compact: 通過一系列insert、delete操作, 將數(shù)據(jù)盡量排列在段的前面。 在這個過程中需要在表上加RX鎖, 即只在需要移動的行上加鎖。由于涉及到rowid的改變, 需要enable row movement, 同時要disable基于rowid的trigger。 這一過程對業(yè)務(wù)影響比較小。 2. HWM調(diào)整: 執(zhí)行ALTER TABLE test SHRINK SPACE: 調(diào)整HWM位置, 釋放空閑數(shù)據(jù)塊第一步中的結(jié)果已經(jīng)存儲到磁盤,不會重新在整理碎片,只是收縮高水位,釋放空間。此過程需要在表上加X鎖, 會造成表上的所有DML語句阻塞。在業(yè)務(wù)特別繁忙的系統(tǒng)上可能造成比較大的影響。 ? ? 如果系統(tǒng)業(yè)務(wù)比較繁忙, 可以先執(zhí)行shrink space compact重組數(shù)據(jù), 然后在業(yè)務(wù)不忙的時候再執(zhí)行shrink space降低HWM釋放空閑數(shù)據(jù)塊。 ? ? | ? |
| 我們先看下shrink的工作原理,shrink的算法是從segment的底部開始,移動row到segment的頂部,移動的過程相當(dāng)于delete/insert操作的組合,在這個過程中會產(chǎn)生大量的undo和redo信息。在HP Unix上還存在BUG,在10.1.0.3.0中,在shrink的時候可能會觸發(fā)BUG 3888229,產(chǎn)生巨大數(shù)量的redo和undo。move是直接移動數(shù)據(jù)塊的位置,鑒于上面的原因,在使用shrink的時候,耗時可能非常長,通常慢于move。 對于空間的要求,shrink不需要額外的空間,move需要兩倍的空間。 通過上面的分析,shrink雖然有online的特性,但是也存在很多問題,所以,在進(jìn)行表碎片整理的時候,還是建議停機(jī)檢修,使用move,以下是一些move時候的注意點(diǎn):? | ? | |
| 1. move過程中需要額外的表空間,需要的大小大約等于當(dāng)前表中數(shù)據(jù)量的大小,move結(jié)束后立即釋放該額外空間。? 2. move過程中對表加排它鎖,會影響其他session的DML操作。? 3. move操作并不會維護(hù)索引,因此move完畢后需要對索引rebuild。? 4. move操作會降低HWM,但是并不會釋放HWM以上的空塊,也就是說,move只會對HWM以下的塊進(jìn)行操作。? 5. move操作的一些相關(guān)測試數(shù)據(jù):以2000000數(shù)據(jù)(233M)為例,刪除800000條數(shù)據(jù),執(zhí)行move操作。? 大概用時4秒,共產(chǎn)生了319K的redo,56K的undo。表由233M縮小至145M。? 6. move操作可以完全消除行遷移。? 7. move操作后,為表分配的數(shù)據(jù)段位置發(fā)生了改變,即段頭塊的位置發(fā)生了改變。 | shrink過程中并沒有用到額外的表空間。 shrink操作其實(shí)可以分為兩步:? 第一步:對數(shù)據(jù)進(jìn)行重組,即只會整理碎片,不會降低高水位,也就是說不會釋放空間。? 通過一系列的delete/insert組合來完成,具體的語法是 alter table t1 shrink space compact。該過程會在表上加共享鎖,在移動的行中加排它鎖。并且會維護(hù)索引。? 第二步:降低HWM,回收空間,與move不同的是,shrink可以回收HWM以上的塊。該過程會在表上加排它鎖,因此業(yè)務(wù)繁忙時并不適合執(zhí)行該降低HWM的操作。 shrink操作會維護(hù)索引,但是不會對索引進(jìn)行碎片整理。如果加入cascade選項,那么維護(hù)索引的同時會對索引進(jìn)行碎片整理。 shrink操作的一些相關(guān)測試數(shù)據(jù):以2000000數(shù)據(jù)(233M)為例,刪除800000條數(shù)據(jù),分兩步執(zhí)行shrink操作。? 數(shù)據(jù)重組大概用時1分鐘58秒,共產(chǎn)生了895M的redo,353M的undo。回收HWM階段僅用1秒,產(chǎn)生了4K的redo,1K的undo。表由233M縮小至226M。 shrink操作不能完全消除行遷移。 shrink操作后,為表分配的數(shù)據(jù)段位置并沒有發(fā)生變化,即段頭塊的位置沒有改變。 | ? |
| create table HWM as select * from dba_objects;SQL> SELECT segment_name, segment_type, blocks FROM dba_segmentsWHERE segment_name='HWM'; DBA_SEGMENTS.BLOCKS 表示分配給這個表的所有的數(shù)據(jù)庫塊的數(shù)目SQL> ANALYZE TABLE hwm ESTIMATE STATISTICS; SQL> SELECT table_name,num_rows,blocks,empty_blocksFROM user_tablesWHERE table_name='HWM';USER_TABLES.BLOCKS表示已經(jīng)使用過的數(shù)據(jù)庫塊的數(shù)目,即水線。
USER_TABLES.EMPTY_BLOCKS 代表分配給該表,
但是在水線以上的數(shù)據(jù)庫塊,即從來沒有使用的數(shù)據(jù)塊。BLOCKS + EMPTY_BLOCKS (700+323=1023)比DBA_SEGMENTS.BLOCKS少1個數(shù)據(jù)庫塊,
這是因?yàn)橛幸粋€數(shù)據(jù)庫塊被保留用作segment header。
DBA_SEGMENTS.BLOCKS 表示分配給這個表的所有的數(shù)據(jù)庫塊的數(shù)目。
USER_TABLES.BLOCKS表示已經(jīng)使用過的數(shù)據(jù)庫塊的數(shù)目。SQL> SELECT COUNT (DISTINCTDBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)||DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) "Used"FROM hwm;有多少塊容納數(shù)據(jù)SQL> delete from hwm;
SQL> commit;
SQL> ANALYZE TABLE hwm ESTIMATE STATISTICS;
SQL> SELECT table_name,num_rows,blocks,empty_blocksFROM user_tablesWHERE table_name='HWM';SQL> TRUNCATE TABLE hwm;
SQL> ANALYZE TABLE hwm ESTIMATE STATISTICS;
SQL> SELECT table_name,num_rows,blocks,empty_blocksFROM user_tablesWHERE table_name='HWM'; ? | ? | |
| move | alter table xxx move ? ? --壓縮快之后所有索引都會失效,需要重建一下索引 ? 高水位以下合并碎片,同時壓縮表,不移動高水位。 | ? |
| 釋放未 使用空 間 | DEALLOCATE UNUSED為釋放HWM上面的未使用空間,但是并不會釋放HWM下面的自由空間,也不會移動HWM的位置. Alter??table table_name deallocate unused | ? |
| 查詢失效索引語句 | select index_name,table_name,tablespace_name,status From dba_indexes Where owner='ISC' And status<>'VALID'; | ? |
| ? | select file_id,bytes/1024/1024 from dba_free_space where tablespace_name='TEST'; | ? |
| ? | 普通表 ?????????Sql腳本,改腳本會生成相應(yīng)的語句 ?????????select'alter table '||table_name||' enable row movement;'||chr(10)||'alter table '||table_name||' shrink space;'||chr(10)from user_tables; ?????????select'alter index '||index_name||' shrink space;'||chr(10)from user_indexes; ?????????分區(qū)表 ?????????進(jìn)行shrink space時 發(fā)生ORA-10631錯誤.shrink space有一些限制. ?????????在表上建有函數(shù)索引(包括全文索引)會失敗。 ?????????Sql腳本,改腳本會生成相應(yīng)的語句???? | ? |
| ? | select 'alter table '||table_name||' enable row movement;'||chr(10)||' alter table '||table_name||' shrink space;'||chr(10) from user_tables where ;select 'alter index '||index_name||' shrink space;'||chr(10) from user_indexes where uniqueness='NONUNIQUE' ;select 'alter table '||segment_name||' modify subpartition ' ||partition_name||' shrink space;'||chr(10) from user_segments where segment_type='TABLE SUBPARTITION' '; | ? |
| 啟動關(guān)閉行遷移 | alter table?table_name?enable row movement ; alter table?table_name disable row movement;? 注意, alter table table_name row movement語句會造成引用表table_name的對象(如存儲過程、包、視圖等)變?yōu)闊o效。 需要執(zhí)行utlrp.sql來編譯無效的對象。? | ? |
| 把碎片率高的表找出,按表的空間大小排序找出來,不支持壓縮表 | select 'drop table ' || segment_name || ' purge;', sum(bytes)/1024/1024 Mbytese? from user_segments a , user_tables b where segment_type='TABLE' ? and a.segment_name=b.TABLE_NAME? and b.COMPRESSION='DISABLED'? group by segment_name,COMPRESSION? order by sum(bytes)/1024/1024 desc; | ? |
| SHRINK(收縮)? | alter table table_name shrink space [<null> | compact | cascade] ; 大表可同時降低表自身和表空間的高水位線,小表則只可以降低表自身的高水位線 ? 收縮表, 相當(dāng)于把塊中數(shù)據(jù)打結(jié)實(shí)了, 但會保持high water mark 。 ? 收縮表, 降低high water mark, 并把相關(guān)索引也要收縮一下。 回縮索引。 | ? |
| ? 統(tǒng)計信息 | 因?yàn)樗械男畔⒍际歉鶕?jù)dba_tables,表的信息是根據(jù)統(tǒng)計信息得到的,所以如果統(tǒng)計信息不準(zhǔn)確,那么整個搜索的結(jié)果都可能是錯誤的 exec dbms_stats.gather_table_stats('user','table_name'); exec dbms_stats.gather_table_stats(user,'test1',estimate_percent=>100); exec dbms_stats.gather_table_stats(user,'ISC_USER',CASCADE=>TRUE); ? select table_name,last_analyzed from user_tables where table_name = 'ISC_USER' order by last_analyzed desc ; | ? |
| ?查找數(shù)據(jù)庫中某個表空間下,可以實(shí)際存儲和需要的表空間差別最大的表 | SELECT NUM_ROWS,AVG_ROW_LEN*NUM_ROWS/1024/1024/0.9 NEED, BLOCKS*8/1024 TRUE, (BLOCKS*8/1024-AVG_ROW_LEN*NUM_ROWS/1024/1024/0.9) RECOVER_MB, TABLE_NAME FROM dba_tables WHERE tablespace_name='PSAPSR3' AND BLOCKS*8/1024-AVG_ROW_LEN*NUM_ROWS/1024/1024/0.9>100 SELECT table_name, ROUND((blocks * 8/1024), 2) "高水位空間 M", ROUND((num_rows * avg_row_len / 1024/1024), 2) "真實(shí)使用空間 M", ROUND((blocks * 10 / 100) * 8, 2) "預(yù)留空間(pctfree) M", ROUND((blocks * 8 - (num_rows * avg_row_len / 1024) -blocks * 8 * 10 / 100), 2) "浪費(fèi)空間 M", ((blocks * 8-(num_rows * avg_row_len / 1024))/1024)/(blocks * 8/1024) "浪費(fèi)空間 %" FROM user_tables WHERE table_name = 'ISC_USER'; | ? |
| Oracle 9i: ???????(1)如果是INEXTENT,?可以使alter table tablename deallocate unused將HWM以上所有沒使用的空間釋放 ???????(2)?如果MINEXTENT >HWM?則釋放MINEXTENTS?以上的空間。如果要釋放HWM以上的空間則使用KEEP 0。 ???????SQL>alter table tablesname deallocate unused keep 0; ???????(3)truncate table drop storage(缺省值)命令可以將MINEXTENT?之上的空間完全釋放(交還給操作系統(tǒng)),并且重置HWM。 ???????(4)如果僅是要移動HWM,而不想讓表長時間鎖住,可以用truncate table reuse storage,僅將HWM重置。 ???????(5)ALTER TABLE MOVE會將HWM移動,但在MOVE時需要雙倍的表空間,而且如果表上有索引的話,需要重構(gòu)索引 ???????(6)DELETE表不會重置HWM,也不會釋放自由的空間(也就是說DELETE空出來的空間只能給對象本身將來的INSERT/UPDATE使用,不能給其它的對象使用) ? Oracle 10g: ???????(1)可以使用alter table test_tab shrink space命令來聯(lián)機(jī)移動hwm, ???????(2)如果要同時壓縮表的索引,可以發(fā)布:alter table test_tab shrink space cascade | ? | |
?
總結(jié)
以上是生活随笔為你收集整理的oracle高水位线的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Iptables防火墙原理
- 下一篇: Mysql截取中英数混合的字符串