高水位(HIGH WARTER MARK,HWM)好比水庫中儲水的水位,用於描述數據庫中段的擴展方式。高水位對全表掃描方式有着至關重要的影響。當使用DELETE刪除表記錄時,高水位並不會下降,隨之導致的是全表掃描的實際開銷並沒有任何減少。
例如,首先新建一張空表,大小占用64K,然后插入數據直到表大小變為50G,此時使用DELETE刪除所有的數據並且提交,這個時候查詢表的大小的時候依然是50G,這就是因為表的高水位沒有釋放的緣故,而在這時如果使用“SELECT * FROM TABLE_NAME;”語句來查詢數據的話,那么查詢過程就會很慢,因為Oracle要執行全表掃描,從高水位下所有的塊都得去掃描,直到50G的所有塊全部掃描完畢。曾遇到一個同事使用DELETE刪除了一個很大的分區表,然后執行SELECT查詢很久都沒有結果,以為是數據庫HANG住了,其實這個問題是由於高水位的緣故。所以,表執行了TRUNCATE操作,再次SELECT的時候就可以很快返回結果了。
釋放表的高水位通常有如下幾種辦法:
(1)對表進行MOVE操作:ALTER TABLE TABLE_NAME MOVE;。若表上存在索引,則記得重建索引。
(2)對表進行SHRINK SPACE操作:ALTER TABLE TABLE_NAME SHRINK SPACE;,注意,在執行該指令之前必須開啟行移動:ALTER TABLE TABLE_NAME ENABLE ROW MOVEMENT;。該方法的優點是:在碎片整理結束后,表上相關的索引仍然有效,缺點是會產生大量的UNDO和REDO。
(3)復制要保留的數據到臨時表T,DROP原表,然后RENAME臨時表T為原表。
(4)exp/imp或expdp/impdp重構表。
(5)若表中沒有數據則直接使用TRUNCATE來釋放高水位。
如何找出系統中哪些表擁有高水位呢?這里給出兩種辦法,①比較表的行數和表的大小關系。如果行數為0,而表的當前占用大小減去初始化時的大小(INITIAL_EXTENT)后依然很大,那么說明該表有高水位。②行數和塊數的比率,即查看一個塊可以存儲多少行數據。如果一個塊存儲的行數少於5行甚至更少,那么說明有高水位。注意,這兩種方法都不是十分准確,需要再對查詢結果進行篩選。需要注意的是,在查詢表的高水位時,首先需要分析表,以得到最准確的統計信息。
下面給出用於查詢高水位的幾個SQL語句:
SELECT D.OWNER, ROUND(D.NUM_ROWS / D.BLOCKS, 2), D.NUM_ROWS, D.BLOCKS, D.TABLE_NAME, ROUND((d.BLOCKS*8-D.INITIAL_EXTENT/1024)/1024) t_size FROM DBA_TABLES D WHERE D.BLOCKS > 10 AND ROUND(D.NUM_ROWS / D.BLOCKS, 2) < 5 AND d.OWNER NOT LIKE '%SYS%' ; 或: SELECT OWNER, SEGMENT_NAME TABLE_NAME, SEGMENT_TYPE, GREATEST(ROUND(100 * (NVL(HWM - AVG_USED_BLOCKS, 0) / GREATEST(NVL(HWM, 1), 1)), 2), 0) WASTE_PER FROM (SELECT A.OWNER OWNER, A.SEGMENT_NAME, A.SEGMENT_TYPE, B.LAST_ANALYZED, A.BYTES, B.NUM_ROWS, A.BLOCKS BLOCKS, B.EMPTY_BLOCKS EMPTY_BLOCKS, A.BLOCKS - B.EMPTY_BLOCKS - 1 HWM, DECODE(ROUND((B.AVG_ROW_LEN * NUM_ROWS * (1 + (PCT_FREE / 100))) / C.BLOCKSIZE, 0), 0, 1, ROUND((B.AVG_ROW_LEN * NUM_ROWS * (1 + (PCT_FREE / 100))) / C.BLOCKSIZE, 0)) + 2 AVG_USED_BLOCKS, ROUND(100 * (NVL(B.CHAIN_CNT, 0) / GREATEST(NVL(B.NUM_ROWS, 1), 1)), 2) CHAIN_PER, B.TABLESPACE_NAME O_TABLESPACE_NAME FROM SYS.DBA_SEGMENTS A, SYS.DBA_TABLES B, SYS.TS$ C WHERE A.OWNER = B.OWNER AND SEGMENT_NAME = TABLE_NAME AND SEGMENT_TYPE = 'TABLE' AND B.TABLESPACE_NAME = C.NAME) WHERE GREATEST(ROUND(100 * (NVL(HWM - AVG_USED_BLOCKS, 0) / GREATEST(NVL(HWM, 1), 1)), 2), 0) > 50 AND OWNER NOT LIKE '%SYS%' AND BLOCKS > 100 ORDER BY WASTE_PER DESC;
最后再次提醒各位讀者,若表執行了大量的DELETE操作后,則最好回收一下表的高水位。
http://docs.oracle.com/cd/E11882_01/server.112/e40540/logical.htm#CNCPT89022
Segment Space and the High Water Mark
To manage space, Oracle Database tracks the state of blocks in the segment. The high water mark (HWM) is the point in a segment beyond which data blocks are unformatted and have never been used.
MSSM uses free lists to manage segment space. At table creation, no blocks in the segment are formatted. When a session first inserts rows into the table, the database searches the free list for usable blocks. If the database finds no usable blocks, then it preformats a group of blocks, places them on the free list, and begins inserting data into the blocks. In MSSM, a full table scan reads allblocks below the HWM.
ASSM does not use free lists and so must manage space differently. When a session first inserts data into a table, the database formats a single bitmap block instead of preformatting a group of blocks as in MSSM. The bitmap tracks the state of blocks in the segment, taking the place of the free list. The database uses the bitmap to find free blocks and then formats each block before filling it with data. ASSM spread out inserts among blocks to avoid concurrency issues.
Every data block in an ASSM segment is in one of the following states:
-
Above the HWM
These blocks are unformatted and have never been used.
-
Below the HWM
These blocks are in one of the following states:
-
Allocated, but currently unformatted and unused
-
Formatted and contain data
-
Formatted and empty because the data was deleted
-
Figure 12-23 depicts an ASSM segment as a horizontal series of blocks. At table creation, the HWM is at the beginning of the segment on the left. Because no data has been inserted yet, all blocks in the segment are unformatted and never used.
Figure 12-23 HWM at Table Creation
Description of "Figure 12-23 HWM at Table Creation"
段空間和高水位標記 |
oracle數據庫通過跟蹤段中的塊狀態來管理空間。高水位標記(HWM)是段中的一個點,超過該點的數據塊是未格式化和未使用過的。 |
MSSM使用空閑列表來管理段空間。在創建表時,段中的塊並未被格式化。當一個會話初次向表中插入行時,數據庫將搜索空閑列表來查找可用的塊。如果數據庫未找到可用的塊,那么它會預格式化一組塊,並將它們放置在空閑列表中,並開始將數據插入到塊中。在MSSM中,全表掃描會讀取HWM之下的所有塊。 |
ASSM不使用空閑列表,所以必須以不同的方式管理空間。當會話初次向表中插入數據時,數據庫只格式化一個單一位圖塊,而不像在MSSM中那樣預格式化一組塊。位圖取代了空閑列表,用於跟蹤在段中的塊的狀態。數據庫使用位圖來查找可用的塊,然后在往塊寫入數據之前將其格式化。ASSM將插入操作分散到多個塊,以避免並發問題。 |
在一個ASSM段中的每個數據塊處於以下狀態之一: |
l 在HWM之上 這些塊是未格式化的,且從未使用過。 l 在HWM之下 這些塊處於以下狀態之一: u 已分配,但當前未格式化且未使用 u 已格式化且包含數據 u 已格式化且為空,因為數據已被刪除 |
圖12-23將一個ASSM段描述為一系列水平的塊。在創建表時,HWM在左側段的開頭。因為還未插入數據,段中的所有塊都還是未格式化且從未使用過。 |
圖將12-23在創建表時的HWM |
Suppose that a transaction inserts rows into the segment. The database must allocate a group of blocks to hold the rows. The allocated blocks fall below the HWM. The database formats a bitmap block in this group to hold the metadata, but does not preformat the remaining blocks in the group.
In Figure 12-24, the blocks below the HWM are allocated, whereas blocks above the HWM are neither allocated or formatted. As inserts occur, the database can write to any block with available space. The low high water mark (low HWM) marks the point below which all blocks are known to be formatted because they either contain data or formerly contained data.
In Figure 12-25, the database chooses a block between the HWM and low HWM and writes to it. The database could have just as easily chosen any other block between the HWM and low HWM, or any block below the low HWM that had available space. In Figure 12-25, the blocks to either side of the newly filled block are unformatted.
The low HWM is important in a full table scan. Because blocks below the HWM are formatted only when used, some blocks could be unformatted, as in Figure 12-25. For this reason, the database reads the bitmap block to obtain the location of the low HWM. The database reads all blocks up to the low HWM because they are known to be formatted, and then carefully reads only the formatted blocks between the low HWM and the HWM.
Assume that a new transaction inserts rows into the table, but the bitmap indicates that insufficient free space exists under the HWM. In Figure 12-26, the database advances the HWM to the right, allocating a new group of unformatted blocks.
When the blocks between the HWM and low HWM are full, the HWM advances to the right and the low HWM advances to the location of the old HWM. As the database inserts data over time, the HWM continues to advance to the right, with the low HWM always trailing behind it. Unless you manually rebuild, truncate, or shrink the object, the HWM never retreats.
See Also:
-
Oracle Database Administrator's Guide to learn how to shrink segments online
-
Oracle Database SQL Language Reference for TRUNCATE TABLE syntax and semantics
假設一個事務將行插入到段中。數據庫必須分配一組塊來容納這些行。已分配的塊在HWM之下。數據庫格式化該組中的一個位圖塊來容納元數據,但不會預格式化組中其余的塊。
在圖12-24中,HWM之下的塊是已分配的,而HWM之上的塊是既未分配也未格式化的。插入發生時,數據庫可以寫入到任何具有可用空間的塊。由低位高水位標記(低HWM)標記一個點,該點之下的所有塊都已知是已格式化的,要么包含數據,或以前曾包含數據。
在圖12-25中,數據庫選定了HWM和低HWM之間的一個塊,並往其中寫入數據。數據庫也可能會隨意選擇HWM和低HWM之間的任何其他塊,或低HWM之下任何有可用空間的塊。圖12-25中,在新填充塊兩邊的塊都還是未格式化的。
低HWM在全表掃描中非常重要。因為HWM之下的塊只在被使用時才格式化,所以可能還有一些塊是未被格式化的,如圖12-25所示。鑒於此,數據庫讀取位圖塊,以獲取低HWM的位置。數據庫讀取低HWM之下的所有塊,因為已知它們是已格式化的,然后僅仔細讀取位於低 HWM 和 HWM 之間的已格式化塊。
假定一個新事務將行插入到該表,但位圖指示在HWM之下沒有足夠的可用空間。在圖12-26中,數據庫向右推進HWM,分配一組新的未格式化塊。
當HWM與低HWM之間的塊填滿時,HWM向右推進,而低HWM相應推進到舊的HWM的位置。數據庫不斷插入數據,隨着時間的推移,HWM繼續向右推進,而低HWM總尾隨其后。除非您手動重建、截斷、或縮小該對象,否則HWM從不倒退。
備注: 1)move不但可以重置水位線(HWM),解決松散表帶來的 IO 浪費,還可以解決表中的行遷移問題。 move表的話需要雙倍的空間,否則無法成功。move表可以通過重新安排數據文件的空間達到收縮數據文件的目的。 move表時,會產生exclusive lock 鎖,此時只能對表進行 select 操作。 move表之后,如果表上有索引,記得重建。 2)shrink表只對ASSM管理的表有效,相關命令有: -----alter table TABLE_NAME shrink space; 整理碎片並回收空間 -----alter table TABLE_NAME shrink space compact; 只整理碎片,不回收空間 -----alter table TABLE_NAME shrink space cascate; 整理碎片回收空間,並連同表的級聯對象一起整理(比如索引) 能在線進行,不影響表上的DML操作,當然,並發的DML操作在shrink結束的時刻會出現短暫的block; shrink的另外一個優點是在碎片整理結束后,表上相關的index仍然enable。 3)move的操作速度遠遠快於shrink 操作 ,不是一般的快,不是一個數量級的,而且shrink 會產生大量的undo 和redo 操作。 4)truncate是DDL操作,相當於刪表后重建。 5)還有其他的方法,如導出后再重新導入。
詳細轉自:http://blog.itpub.net/26736162/viewspace-2139546/