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。