Oracle高水位線


Oracle高水位線

https://blog.csdn.net/jx_jy/article/details/50607790

Oracle高水位線的概念
Oracle里面的對象放到存儲級別都稱為segment(段),比如表段,索引段,回滾段等,這些知識segment的邏輯描述。下面就拿表段為例解釋下。

     在create table的時候可以指定分配給table的初始空間的大小,一般是都少個extent(區間),extent就是多個連續的block。但是我在表中插入數據是個一點點變化的過程。比如我建了一個表,初始分配了8個extents,每個extents由8個block組成,則就相當於給這個表分配了8*8個blocks。再加入我要插入的數據一行的長度為一個塊大小,則我每插入一行就需要使用一個block。

     高水位就是用來標明我以往使用過的塊數的最高位。

     剛開始我沒有插入數據的時候,高水位就在0塊的位置,當我插入1行數據(占用一個塊),則高水位就上升1,指向1塊的位置。就這樣,在不斷的插入數據的過程中,高水位一直在增加,用來標示這個表曾經一共用過的塊數。

     但是,高水位有個這樣的問題,當我刪除數據的時候,高水位線是不會自動降的。

而對於全表掃描,系統要掃描多少個塊,不是為這個表分配了多少塊,而是高水位線以下的所有數據塊。

     所以,我原來有個表,首先插入了100行的數據,高水位線到了100的位置,后來我又刪了99條數據,只剩了一個數據塊有用,但是高水位線依然在100的位置。當我要全表掃描的時候,仍然會把高水位下的100個數據庫全部讀一遍才能返回數據。而實際100個數據塊中只有一個是有用的。

如何查看表的高水位線
首先需要搜集表的統計信息

exec dbms_stats.gather_table_stats(ownname => 'CWCS',tabname => 'GL_FREEVALUE',cascade => true,estimate_percent => 100,method_opt => 'for all indexed column size auto')

     然后查看dba_tables即可

select blocks,

   empty_blocks

from dba_tables

where table_name = 'TMP_WJF'

     其中blocks+empty_blocks就是分配給表的總塊數,blocks就是高水位線。

如何查看表實際使用的數據塊數
使用以下sql

SELECTCOUNT(DISTINCT DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)||DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) ZS

FROM TMP_WJF;

     如果實際用的塊數比高水位線低很多,則調整高水位可顯著改善全表掃描效率。

如何降低高水位。
表收縮
首先激活行遷移,再執行表收縮

altertable TMP_WJF enablemovement;

altertable TMP_WJF shrinkspace;

表收縮的過程大致猜想如下:oracle以行為單位,從表的最后一行開始,然后開始掃描表,發現表前面的數據庫有空間空間時,就將這最后一行插入到新的位置,然后刪除最后一行的數據,以此迭代。

所以,在shrink的過程中,只有部分行的rowid會發生改變,且表所占的塊區域不會改變。

而且在shrink的過程中,oracle會自動維護表相關的索引,所以,若表上索引比較大,則在shrink過程中索引的維護費用也比較大。

     其中altertable TMP_WJF enablemovement;可能會造成表相關的視圖、存儲過程等失效。索引最好在shrink之后執行下utlrp.sql編譯下無效對象。

  Shrink過程分兩個過程

  數據重組過程,這個過程只會在需要移動的行上加排他鎖。因此對業務影響較小。因為涉及到rowid的變更,需要enable movement和禁用基於rowid的trigger。

降低HWM過程,這個過程會在全表上加排他鎖,所以會阻塞所有關於這個表的DML操作,所以,對業務繁忙的系統還是會造成比較大的影響。

可以使用altertable TMP_WJF shrinkspace compat;只進行數據重組過程,等業務閑了再altertable TMP_WJF shrinkspace降低高水位。

表重建
altertable TMP_WJF move;

此種方式,在表空間內,至少有兩倍該表所占空間的空間才能實施重建。而且該方式不會減少預先為表分配的數據塊總數。

對於move操作,會在一塊新的區域內拷貝原表的數據,所以,move操作后,表所占的區域也發生了改變,所有行的rowid也發生了改變。

Move操作並不會同步維護索引等相關對象,因此,在move完之后要對索引進行rebuild。

在整個move操作中,會對表加上排他鎖,所有的DML操作將會被阻塞,只能進行select。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM