您好,登錄后才能下訂單哦!
高水位(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語句:
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
段空間和高水位標記 |
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.
Figure 12-24 HWM and Low HWM
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.
Figure 12-25 HWM and Low HWM
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.
Figure 12-26 Advancing HWM and Low HWM
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
move
不但可以重置水位線(HWM),解決松散表帶來的 IO 浪費,還可以解決表中的行遷移問題。全表掃先讀段頭塊,而后在段頭塊里面找到HWM
下面用實驗由內而外來理解Oracle的HWM
先來理清dba_tables里面的字段blocks的含義
dba_tables.blocks記錄的是分析得到的 formatted block 的總數
而 low hwm 和 high hwm之間可能同時存在 formatted block 和 unfomatted block
所以準確地說 blocks 不能代表 low hwm 或high hwm
如果 low hwm 和 high hwm之間正好沒有formatted block時,dba_tables.blocks和low hwm下的blocks一致
那么什么是Oracle中未格式化的塊呢?
未格式化,意思就是這個塊,已經是屬于這個段了,但是還保留著原來的樣子沒動
格式化就是把塊中的數據清除掉,并把塊頭改為這個對象的
MSSM表空間中的段,只有一個高水位,高水位下的塊都是格式化了的
但是ASSM表空間中的段,有兩個高水位:低高水位和高高水位
即上文trc里的:Highwater:: 0x01000189和Low HighWater Mark Highwater:: 0x01000189
低高水位下的塊全部是格式化了的
但是低高水位和高高水位之間的塊,則可能是格式化了的,也可能是沒有
現在的t的高高水位是file 4,block 393;其低高水位是file 4,block 393
我們現在再來看一下t現在data_object_id是多少:
等等.......
4. 修正ORACLE 表的高水位線
在ORACLE 中,執行對表的刪除操作不會降低該表的高水位線。而全表掃描將始終讀取一個段(extent) 中所有低于高水位線標記的塊。如果在執行刪除操作后不降低高水位線標記,則將導致查詢語句的性能低下。
下面的方法都可以 降低高水位線標記 。
1. 執行表重建指令 alter table table_name move;
在線轉移表空間ALTER TABLE ... MOVE TABLESPACE ..
當你創建了一個對象如表以后, 不管你有沒有插入數據 , 它都會占用一些塊 ,ORACLE 也會給它分配必要的空間 . 同樣 , 用 ALTER TABLE MOVE 釋放自由空間后 , 還是保留了一些空間給這個表 .
ALTER TABLE ... MOVE 后面不跟參數也行,不跟參數表還是在原來的表空間, M ove后記住重建索引 . 如果以后還要繼續向這個表增加數據,沒有必要move , 只是釋放出來的空間,只能這個表用,其他的表或者 segment 無法使用該空間 。
2. 執行alter table table_name shrink space;
注意, 此命令為Oracle 10g 新增功能 ,再執行該指令之前必須允許行移動 alter table table_name enable row movement;
3. 復制要保留的數據到臨時表t , drop 原表,然后 rename 臨時表 t 為原表
4. 用邏輯導入導出: E mp/ I mp
5. A lter table table_name deallocate unused
注: 這證明,DEALLOCATE UNUSED 為釋放 HWM 上面的未使用空間 , 但是并不會釋放 HWM 下面的自由空間 , 也不會移動 HWM 的位置 .
6. 盡量使用 truncate .
注意:
在9I 中 :
1. 如果是 INEXTENT , 可以使ALTER TABLE TABLENAME DEALLOCATE UNUSED 將 HWM 以上所有沒使用的空間釋放
2. 如果MINEXTENT >HWM 則釋放 MINEXTENTS 以上的空間。如果要釋放 HWM 以上的空間則使用 KEEP 0 。
ALTER TABLE TABLESNAME DEALLOCATE UNUSED KEEP 0;
3. TRUNCATE TABLE DROP STORAGE (缺省值 ) 命令可以將MINEXTENT 之上的空間完全釋放 (交還給操作系統 ), 并且重置 HWM 。
4. 如果僅是要移動HWM, 而不想讓表長時間鎖住 , 可以用 TRUNCATE TABLE REUSE STORAGE, 僅將 HWM 重置。
5. ALTER TABLE MOVE會將 HWM 移動 , 但在 MOVE 時需要雙倍的表空間 , 而且如果表上有索引的話 , 需要重構索引
6. DELETE表不會重置 HWM, 也不會釋放自由的空間 ( 也就是說 DELETE 空出來的空間只能給對象本身將來的 INSERT/UPDATE 使用 , 不能給其它的對象使用 )
在ORACLE 10G:
1. 可以使用ALTER TABLE TEST_TAB SHRINK SPACE 命令來聯機移動 HWM,
2. 如果要同時壓縮表的索引, 可以發布 :ALTER TABLE TEST_TAB SHRINK SPACE CASCADE
5. HWM 特點:
1. ORACLE用 HWM 來界定一個段中使用的塊和未使用的塊 .
舉個例子來說, 當我們創建一個表時 ,ORACLE 就會為這個對象分配一個段 . 在這個段中 , 即使我們未插入任何記錄 , 也至少有一個區被分配 , 第一個區的第一個塊就稱為段頭 (SEGMENT HEADE), 段頭中就儲存了一些信息 , 基中 HWM 的信息就存儲在此 . 此時 , 因為第一個區的第一塊用于存儲段頭的一些信息 , 雖然沒有存儲任何實際的記錄 , 但也算是被使用 , 此時 HWM 是位于第 2 個塊 . 當我們不斷插入數據到 表 后, 第 1 個塊已經放不下后面新插入的數據 , 此時 ,ORACLE 將高水位之上的塊用于存儲新增數據 , 同時 ,HWM 本身也向上移 . 也就是說 , 當我們不斷插入數據時 ,HWM 會往不斷上移 , 這樣 , 在 HWM 之下的 , 就表示使用過的塊 ,HWM 之上的就表示已分配但從未使用過的塊 .
2. HWM在插入數據時 , 當現有空間不足而進行空間的擴展時會向上移 , 但刪除數據時不會往下移 .
這就好比是水庫的水位, 當漲水時 , 水位往上移 , 當水退出后 , 最高水位的痕跡還是清淅可見 .
ORACLE 不會釋放空間以供其他對象使用,有一條簡單的理由:由于空間是為新插入的行保留的,并且要適應現有行的增長。被占用的最高空間稱為最高使用標記 (HWM) ,
3. HWM的信息存儲在段頭當中 .
HWM本身的信息是儲存在段頭 . 在段空間是手工管理方式時 ,ORACLE 是通過 FREELIST( 一個單向鏈表 ) 來管理段內的空間分配 . 在段空間是自動管理方式時 (ASSM),ORACLE 是通過 BITMAP 來管理段內的空間分配 .
4. ORACLE的全表掃描是讀取高水位標記 (HWM) 以下的所有塊 .
所以問題就產生了. 當用戶發出一個全表掃描時, ORACLE 始終必須從段一直掃描到 HWM ,即使它什么也沒有發現。該任務延長了全表掃描的時間。
5. 當用直接路徑插入行時 , 即使HWM 以下有空閑的數據庫塊,鍵入在插入數據時使用了 append關鍵字,則在插入時使用 HWM 以上的數據塊,此時 HWM 會自動增大。
一、什么是水線(High Water Mark)?
所有的oracle段(segments,在此,為了理解方便,建議把segment作為表的一個同義詞) 都有一個在段內容納數據的上限,我們把這個上限稱為"high water mark"或HWM。這個HWM是一個標記,用來說明已經有多少沒有使用的數據塊分配給這個segment。HWM通常增長的幅度為一次5個數據塊,原則上HWM只會增大,不會縮小,即使將表中的數據全部刪除,HWM還是為原值,由于這個特點,使HWM很象一個水庫的歷史最高水位,這也就是HWM的原始含義,當然不能說一個水庫沒水了,就說該水庫的歷史最高水位為0。但是如果我們在表上使用了truncate命令,則該表的HWM會被重新置為0。
二、HWM數據庫的操作有如下影響:
a) 全表掃描通常要讀出直到HWM標記的所有的屬于該表數據庫塊,即使該表中沒有任何數據。
b) 即使HWM以下有空閑的數據庫塊,鍵入在插入數據時使用了append關鍵字,則在插入時使用HWM以上的數據塊,此時HWM會自動增大。
三、如何知道一個表的HWM?
a) 首先對表進行分析:
ANALYZE TABLE <tablename> ESTIMATE/COMPUTE STATISTICS;
b) SELECT blocks, empty_blocks, num_rows
FROM user_tables
WHERE table_name = <tablename>;
說明:
BLOCKS 列代表該表中曾經使用過得數據庫塊的數目,即水線。
EMPTY_BLOCKS 代表分配給該表,但是在水線以上的數據庫塊,即從來沒有使用的數據塊。
讓我們以一個有28672行的BIG_EMP1表為例進行說明:
1) SQL> SELECT segment_name, segment_type, blocks
FROM dba_segments
WHERE segment_name='BIG_EMP1';
SEGMENT_NAME SEGMENT_TYPE BLOCKS
----------------- -------------- ---------
BIG_EMP1 TABLE 1024
1 row selected.
2) SQL> ANALYZE TABLE big_emp1 ESTIMATE STATISTICS;
Statement processed.
3) SQL> SELECT table_name,num_rows,blocks,empty_blocks
FROM user_tables
WHERE table_name='BIG_EMP1';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
---------- -------- ------- -------------
BIG_EMP1 28672 700 323
1 row selected.
注意:
BLOCKS + EMPTY_BLOCKS (700+323=1023)比DBA_SEGMENTS.BLOCKS少1個數據庫塊,這是因為有一個數據庫塊被保留用作segment header。DBA_SEGMENTS.BLOCKS 表示分配給這個表的所有的數據庫塊的數目。USER_TABLES.BLOCKS表示已經使用過的數據庫塊的數目。
4) SQL> SELECT COUNT (DISTINCT
DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)||
DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) "Used"
FROM big_emp1;
Used
----------
700
1 row selected.
5) SQL> delete from big_emp1;
28672 rows processed.
6) SQL> commit;
Statement processed.
7) SQL> ANALYZE TABLE big_emp1 ESTIMATE STATISTICS;
Statement processed.
8) SQL> SELECT table_name,num_rows,blocks,empty_blocks
FROM user_tables
WHERE table_name='BIG_EMP1';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
--------- -------- ------- ----------
BIG_EMP1 0 700 323
1 row selected.
9) SQL> SELECT COUNT (DISTINCT
DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid)||
DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) "Used"
FROM big_emp1;
Used
----------
0 ----這表名沒有任何數據庫塊容納數據,即表中無數據
1 row selected.
10) SQL> TRUNCATE TABLE big_emp1;
Statement processed.
11) SQL> ANALYZE TABLE big_emp1 ESTIMATE STATISTICS;
Statement processed.
12) SQL> SELECT table_name,num_rows,blocks,empty_blocks
2> FROM user_tables
3> WHERE table_name='BIG_EMP1';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
---------- -------- -------- ------------
BIG_EMP1 0 0 511
1 row selected.
13) SQL> SELECT segment_name,segment_type,blocks
FROM dba_segments
WHERE segment_name='BIG_EMP1';
SEGMENT_NAME SEGMENT_TYPE BLOCKS
------------ ------------- ------
BIG_EMP1 TABLE 512
1 row selected.
注意:
TRUNCATE命令回收了由delete命令產生的空閑空間,注意該表分配的空間由原先的1024塊降為512塊。
為了保留由delete命令產生的空閑空間,可以使用TRUNCATE TABLE big_emp1 REUSE STORAGE.
用此命令后,該表還會是原先的1024塊。
四、Oracle表段中的高水位線HWM
在Oracle數據的存儲中,可以把存儲空間想象為一個水庫,數據想象為水庫中的水。水庫中的水的位置有一條線叫做水位線,在Oracle中,這條線被稱為高水位線(High-warter mark, HWM)。在數據庫表剛建立的時候,由于沒有任何數據,所以這個時候水位線是空的,也就是說HWM為最低值。當插入了數據以后,高水位線就會上漲,但是這里也有一個特性,就是如果你采用delete語句刪除數據的話,數據雖然被刪除了,但是高水位線卻沒有降低,還是你剛才刪除數據以前那么高的水位。也就是說,這條高水位線在日常的增刪操作中只會上漲,不會下跌。
下面我們來談一下Oracle中Select語句的特性。Select語句會對表中的數據進行一次掃描,但是究竟掃描多少數據存儲塊呢,這個并不是說數據庫中有多少數據,Oracle就掃描這么大的數據塊,而是Oracle會掃描高水位線以下的數據塊。現在來想象一下,如果剛才是一張剛剛建立的空表,你進行了一次Select操作,那么由于高水位線HWM在最低的0位置上,所以沒有數據塊需要被掃描,掃描時間會極短。而如果這個時候你首先插入了一千萬條數據,然后再用delete語句刪除這一千萬條數據。由于插入了一千萬條數據,所以這個時候的高水位線就在一千萬條數據這里。后來刪除這一千萬條數據的時候,由于delete語句不影響高水位線,所以高水位線依然在一千萬條數據這里。這個時候再一次用select語句進行掃描,雖然這個時候表中沒有數據,但是由于掃描是按照高水位線來的,所以需要把一千萬條數據的存儲空間都要掃描一次,也就是說這次掃描所需要的時間和掃描一千萬條數據所需要的時間是一樣多的。所以有時候有人總是經常說,怎么我的表中沒有幾條數據,但是還是這么慢呢,這個時候其實奧秘就是這里的高水位線了。
那有沒有辦法讓高水位線下降呢,其實有一種比較簡單的方法,那就是采用TRUNCATE語句進行刪除數據。采用TRUNCATE語句刪除一個表的數據的時候,類似于重新建立了表,不僅把數據都刪除了,還把HWM給清空恢復為0。所以如果需要把表清空,在有可能利用TRUNCATE語句來刪除數據的時候就利用TRUNCATE語句來刪除表,特別是那種數據量有可能很大的臨時存儲表。
在手動段空間管理(Manual Segment Space Management)中,段中只有一個HWM,但是在Oracle9iRelease1才添加的自動段空間管理(Automatic Segment Space Management)中,又有了一個低HWM的概念出來。為什么有了HWM還又有一個低HWM呢,這個是因為自動段空間管理的特性造成的。在手段段空間管理中,當數據插入以后,如果是插入到新的數據塊中,數據塊就會被自動格式化等待數據訪問。而在自動段空間管理中,數據插入到新的數據塊以后,數據塊并沒有被格式化,而是在第一次在第一次訪問這個數據塊的時候才格式化這個塊。所以我們又需要一條水位線,用來標示已經被格式化的塊。這條水位線就叫做低HWM。一般來說,低HWM肯定是低于等于HWM的。
五、修正ORACLE表的高水位線
在ORACLE中,執行對表的刪除操作不會降低該表的高水位線。而全表掃描將始終讀取一個段(extent)中所有低于高水位線標記的塊。如果在執行刪除操作后不降低高水位線標記,則將導致查詢語句的性能低下。下面的方法都可以降低高水位線標記。
1.執行表重建指令 alter table table_name move;
(在線轉移表空間ALTER TABLE 。。。 MOVE TABLESPACE 。。。ALTER TABLE 。。。 MOVE 后面不跟參數也行,不跟參數表還是在原來的表空間,move后記住重建索引。如果以后還要繼續向這個表增加數據,沒有必要move,只是釋放出來的空間,只能這個表用,其他的表或者segment無法使用該空間)
2.執行alter table table_name shrink space; 注意,此命令為Oracle 10g新增功能,再執行該指令之前必須允許行移動alter table table_name enable row movement;
3.復制要保留的數據到臨時表t,drop原表,然后rename臨時表t為原表
4.emp/imp
5.alter table table_name deallocate unused
6.盡量truncate吧
About Me
...............................................................................................................................
● 本文作者:小麥苗,只專注于數據庫的技術,更注重技術的運用
● 本文在itpub(http://blog.itpub.net/26736162)、博客園(http://www.cnblogs.com/lhrbest)和個人微信公眾號(xiaomaimiaolhr)上有同步更新
● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/
● 本文博客園地址:http://www.cnblogs.com/lhrbest
● 本文pdf版及小麥苗云盤地址:http://blog.itpub.net/26736162/viewspace-1624453/
● 數據庫筆試面試題庫及解答:http://blog.itpub.net/26736162/viewspace-2134706/
● QQ群:230161599 微信群:私聊
● 聯系我請加QQ好友(646634621),注明添加緣由
● 于 2017-05-09 09:00 ~ 2017-05-30 22:00 在魔都完成
● 文章內容來源于小麥苗的學習筆記,部分整理自網絡,若有侵權或不當之處還請諒解
● 版權所有,歡迎分享本文,轉載請保留出處
...............................................................................................................................
拿起手機使用微信客戶端掃描下邊的左邊圖片來關注小麥苗的微信公眾號:xiaomaimiaolhr,掃描右邊的二維碼加入小麥苗的QQ群,學習最實用的數據庫技術。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。