(一)高水位標記(High Water Mark,HWM)的概念
所謂高水位標記,是指一個已經分配的段中,已經使用的空間與未使用的空間的分界線。在表的使用過程中,隨着數據的不斷增多(insert),HWM不斷向數據段未使用部分方向移動,而在刪除數據(delete)的過程中,HWM並不會向反方向移動,即使刪除全部數據,HWM依然不會改變。但是如果使用了truncate命令,則表的HWM會被重置為0。
圖1.segment
(二)高水位標記的影響
- 全表掃描要讀出直到HWM標記的所有的屬於該表的數據塊(used space),即使該表中沒有任何數據;
- 即使HWM下有空閑的數據塊,如果在插入數據時使用了append參數,則在插入數據時使用HWM以上的數據塊,HWM會自動增大。
(三)如何知道一個表的HWM
1.首先對表進行分析
SQL > ANALYZE TABLE table_name ESTIMATE/COMPUTE STATISTICS;
2.查看水線
SELECT blocks, --該表曾經使用過的數據塊的數目,即水線 empty_blocks, --代表分配給該表,但是在水位線以上的數據塊,即從來沒有使用過的數據塊 num_rows FROM user_tables WHERE table_name = ‘table_name’;
*注:在Oracle 11g中,收集數據庫對象信息的最好方法,不再是使用帶ESTIMATE或COMPUTE的ANALYSE語句,而是使用最新的DBMS_STATS包。但是,如果要收集數據庫對象存儲格式的有效性以及收集表與簇中的行遷移、行鏈接情況,還得使用ANALYSE。
(四)Oracle表段中的高水位線
每個Oracle數據塊在ASSM段中都屬於下面的一種狀態:
- 高水位線以上
這些塊未被格式化且從來沒有被使用過。
- 高水位線以下(3類)
--已經分配,但是未格式化和未使用;
--格式化,且含有數據;
--格式化,不含有數據,因為數據被刪除了。
(1)在創建表的時候,HWM位於segment左邊的起始處,因為沒有數據插入,segment中全部的block未被格式化和從未被使用。
(2)假設一個事務將行數據插入到segmnet中,數據庫必須分配一組數據塊去保存行信息,被分配的數據塊全在HWM之下,數據庫格式化一個位圖塊來保存元數據,但是沒有指定是哪一個數據塊。
在HWM以下的數據塊是被分配的,在HWM以上的數據塊從未被分配和格式化。當insert時,數據可以寫到有可用空間的任何塊中。low HWM以下的部分,所有的塊都被格式化,因為它們要么含有數據,要么以前包含數據。
(3)當insert時,數據庫選擇在HWM和low HWM之間的任意一個塊進行寫入,或者是HWM以下的一個有空閑空間的塊進行寫入。下圖中,在Low HWM與HWM之間已寫滿塊的兩側的數據塊還未格式化。
(4)low HWM對於全表掃描是非常重要的。因為HWM以下的數據塊只有在要使用時才格式化,有一些塊還未格式化。基於這個原因,數據庫會去bitmap塊查詢low HWM的位置,然后會去讀low HWM以下的全部數據塊,因為數據庫已經知道這些塊全部被格式化了,對於在low HWM和HWM之間的數據塊,數據庫會挑選那些已經格式化了的數據塊進行讀操作。
(5)假設一個新的事務進行插入操作,但是bitmap指示目前在HWM以下已經沒有足夠的空間了,數據庫會向右移動該segment的HWM,分配一組新的未格式化的數據塊。
(五)降低HWM
降低HWM可以使用rebuild、truncate、shrink、move等操作。
(5.1)SHRINK
shrink技術是一種段收縮技術,可將表與索引高水位以下的碎片進行有效壓縮,並將高水位進行回退。
使用方法如下:
step1. 啟用行移動
SQL > ALTER TABLE table_name ENABLE ROW MOVEMENT;
step2. 壓縮數據及下調HWM
SQL > ALTER TABLE table_name SHRINK SPACE CASCADE; --壓縮表及相關數據段並下調HWM
或
SQL > ALTER TABLE table_name SHRINK SPACE COMPACT; --只壓縮數據不下調HWM SQL > ALTER TABLE table_name SHRINK SPACE; --下調HWM
即該技術可以一次性壓縮數據及下調HWM,也可以分兩個階段進行,第一階段:在業務高峰,只壓縮數據不下調HWM,第二階段:在業務空閑時,下調HWM。
(5.2)MOVE Tablespace
語法為:
SQL > ALTER TABLE table_name MOVE TABLESPACE tablepsace_name;
需要注意:
--MOVE后不跟參數也行,不跟參數還是原來的表空間;
--MOVE后需要重建索引;
--如果以后還要網表里插入數據,沒必要MOVE。MOVE釋放出來的空間,只能這個表使用,其它的表或者segment無法使用。
(5.3)CTAS技術
即重建表技術。
SQL > CREATE TABLE new_table_name AS SELECT * FROM old_table_name; --將表的數據寫入到一張新的表里 SQL > DROP TABLE old_table_name; --刪除舊表 SQL > RENAME table new_table_name TO old_table_name --將新表名更改為舊表名
(5.4)EXP/IMP或EXPDP/IMPDP技術
與CTAS技術相當。
(5.5)DEALLOCATE技術
利用DEALLOCATE技術可以回收HWM以上從未使用過的數據塊。語法如下
SQL > ALTER TABLE table_name DEALLOCATE UNUSED [KEEP integer]; --回收表段HWM以上的空間 SQL > ALTER INDEX index_name DEALLOCATE UNUSED [KEEP integer]; --回收索引段HWM以上的空間
(六)MOVE與SHRINK的區別
MOVE |
SHRINK(僅對ASSM有效) |
|
本質 |
move實際上是block級別的數據塊拷貝,對表進行move后,該表所在blockid會發生改變數據的rowid自然也會發生改變,但是數據在table中的存儲順序並沒有發生改變 |
shrink是對行數據進行移動。對表進行shrink后,部分行數據的rowid發生了變化,而table所位於的block區域的位置卻沒有發生變化。 |
重建索引 |
需要重建 |
可以通過cascade關鍵字重建 |
鎖 |
TM(exclusive) |
TM(SX) |
空間要求 |
需要有原表大的空閑空間 |
不需要額外的空間 |
效果 |
壓縮后會回收空間 |
壓縮后會回收空間 |
詳細例子見下面測試。
(七)高水位問題測試
(8.1)測試目的:
1.了解Oracle統計信息的概念;
2.測試使用delete與truncate刪除數據對HWM的影響[主要目的]
(8.2)主要步驟
(1)創建表test01
create table test01 ( id number, name varchar(15) );
這個時候,去查看表與段的參數
SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST01'; TABLE_NAME BLOCKS EMPTY_BLOCKS ------------------------------ ---------- ------------ TEST01 0 0 SQL> SQL> select 2 ds.segment_name, 3 ds.segment_type, 4 ds.header_file, 5 ds.header_block, 6 ds.bytes, 7 ds.blocks, 8 ds.extents 9 from 10 dba_segments ds 11 where 12 ds.segment_name = 'TEST01'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS ------------- ------------------ ----------- ------------ ---------- ---------- ---------- SQL> exec dbms_stats.gather_table_stats('LIJIAMAN','TEST01'); PL/SQL procedure successfully completed SQL> SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST01'; TABLE_NAME BLOCKS EMPTY_BLOCKS ------------------------------ ---------- ------------ TEST01 0 0 SQL> SQL> select 2 ds.segment_name, 3 ds.segment_type, 4 ds.header_file, 5 ds.header_block, 6 ds.bytes, 7 ds.blocks, 8 ds.extents 9 from 10 dba_segments ds 11 where 12 ds.segment_name = 'TEST01'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS ------------- ------------- ----------- ------------ ---------- ---------- ----------
通過以上結構可以看出,我在創建表后,去查看表信息,發現表擁有的blocks=0,以為是統計信息的問題,使用dbms_stats去重新收集表的基礎信息,結果依然相同。然后查看該表段的信息,發現這個段並不存在。可以說明,數據庫在創建表后,只存儲了表的基本結構信息,只有在插入數據的時候,才會去分配區。
此時由於未分配數據塊,也就不存在高水位線的問題。
(2)我們往test01里面插入10000條數據
SQL> declare 2 i number :=1; 3 begin 4 loop 5 if i > 10000 6 then 7 exit; 8 end if; 9 insert into test01 values(i,'euvcg'); 10 i:=i+1; 11 end loop; 12 commit; 13 end; 14 / PL/SQL procedure successfully completed
再去看一下表與段的統計信息
SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST01'; TABLE_NAME BLOCKS EMPTY_BLOCKS ----------- ---------- ------------ TEST01 0 0 SQL> SQL> select 2 ds.segment_name, 3 ds.segment_type, 4 ds.header_file, 5 ds.header_block, 6 ds.bytes, 7 ds.blocks, 8 ds.extents 9 from 10 dba_segments ds 11 where 12 ds.segment_name = 'TEST01'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS ------------ ------------------ ----------- ------------ ---------- ---------- ---------- TEST01 TABLE 6 162 262144 32 4
表test01的blocks依然為0,我們使用dbms_stats重新收集統計信息,
SQL> exec dbms_stats.gather_table_stats('LIJIAMAN','TEST01');
PL/SQL procedure successfully completed
SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST01'; TABLE_NAME BLOCKS EMPTY_BLOCKS ------------------------------ ---------- ------------ TEST01 28 0 SQL> select 2 ds.segment_name, 3 ds.segment_type, 4 ds.header_file, 5 ds.header_block, 6 ds.bytes, 7 ds.blocks, 8 ds.extents 9 from 10 dba_segments ds 11 where 12 ds.segment_name = 'TEST01'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS ------------ ------------------ ----------- ------------ ---------- ---------- ---------- TEST01 TABLE 6 162 262144 32 4
收集統計信息后,我們對段進行分析,插入10000條數據,oracle一共分配了4個區,每個區包含8個數據塊,每個數據塊大小為8KB。此時,表的統計數據已經有了,但是表的Blocks與段的Blocks數量不同,這是什么引起的呢?通過查看兩個blocks欄位的定義,可以看到:
dba_tables.blocks:該表已經使用的數據塊的數量(Number of used data blocks in the table);
dba_segments.blocks:該段中數據塊的總數(Size, in Oracle blocks, of the segment)。
也就是說還有4個數據塊還未使用。
可以使用ANALYZE進行統計
SQL> analyze table TEST01 compute statistics; Table analyzed SQL> SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST01'; TABLE_NAME BLOCKS EMPTY_BLOCKS ------------------------------ ---------- ------------ TEST01 28 4
經過分析,dba_tables統計的數據塊與dba_segments統計的數據塊數量相同了。
此時的高水位線應該如下:
(3)刪除test01里面的全部數據,重新統計信息,發現數據塊並沒有被回收釋放。這些數據塊(dba_tables.blocks=28)曾經擁有過數據,但是現在數據已被刪除。
SQL> delete from test01; 10000 rows deleted SQL> commit; Commit complete SQL> analyze table test01 compute statistics; Table analyzed SQL> SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST01'; TABLE_NAME BLOCKS EMPTY_BLOCKS ------------------------------ ---------- ------------ TEST01 28 4 SQL> select 2 ds.segment_name, 3 ds.segment_type, 4 ds.header_file, 5 ds.header_block, 6 ds.bytes, 7 ds.blocks, 8 ds.extents 9 from 10 dba_segments ds 11 where 12 ds.segment_name = 'TEST01'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS ------------- ------------------ ----------- ------------ ---------- ---------- ---------- TEST01 TABLE 6 162 262144 32 4
此時的高水位線應該如下:
黑色(used space)里面目前並沒有數據,它僅僅代表曾經被使用過,白色(unused space)代表這些塊已經分配給了test01段,但是還未使用過。
(4)測試完了delete,接下來測試truncate
SQL> truncate table test01; Table truncated --truncate后直接查詢,發現表的統計信息依然未變化,而段的數據塊已經回收了 SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST01'; TABLE_NAME BLOCKS EMPTY_BLOCKS ------------------------------ ---------- ------------ TEST01 28 4 SQL> select 2 ds.segment_name, 3 ds.segment_type, 4 ds.header_file, 5 ds.header_block, 6 ds.bytes, 7 ds.blocks, 8 ds.extents 9 from 10 dba_segments ds 11 where 12 ds.segment_name = 'TEST01'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS -------------- ------------------ ----------- ------------ ---------- ---------- ---------- TEST01 TABLE 6 162 65536 8 1 --執行dbms_stats重新收集統計信息,發現表的blocks已經為0,但是表的blocks與段的blocks並不相等 SQL> exec dbms_stats.gather_table_stats('LIJIAMAN','TEST01'); PL/SQL procedure successfully completed SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST01'; TABLE_NAME BLOCKS EMPTY_BLOCKS ------------------------------ ---------- ------------ TEST01 0 4 SQL> select 2 ds.segment_name, 3 ds.segment_type, 4 ds.header_file, 5 ds.header_block, 6 ds.bytes, 7 ds.blocks, 8 ds.extents 9 from 10 dba_segments ds 11 where 12 ds.segment_name = 'TEST01'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS ------------- ------------------ ----------- ------------ ---------- ---------- ---------- TEST01 TABLE 6 162 65536 8 1 --再使用ANALYZE進行分析,表的empty blocks為8,與段的blocks相等 SQL> analyze table test01 compute statistics; Table analyzed SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST01'; TABLE_NAME BLOCKS EMPTY_BLOCKS ------------------------------ ---------- ------------ TEST01 0 8 SQL> select 2 ds.segment_name, 3 ds.segment_type, 4 ds.header_file, 5 ds.header_block, 6 ds.bytes, 7 ds.blocks, 8 ds.extents 9 from 10 dba_segments ds 11 where 12 ds.segment_name = 'TEST01'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS -------------- ------------------ ----------- ------------ ---------- ---------- ---------- TEST01 TABLE 6 162 65536 8 1
可以發現,truncate后,表的空間已經回收,但是並不等於0,而是一個extent的大小。此時高水位線為:
至於8個數據塊是否有一個被使用(segment header),由於個人能力有限,無法進行分析 –_-
(8.3)結論:通過測試,delete無法降低高水位線,truncate可以。
(八)shrink與move測試
(9.1)測試目的:
1.測試shrink與move的區別,主要是第(七)點列出的區別
(9.2)測試步驟
(1)創建測試表,插入數據,分析表,查看統計信息
--創建表 SQL> create table test02 2 ( 3 id number, 4 name varchar(15) 5 ); Table created --插入1000萬條數據 SQL> declare 2 i number :=1; 3 begin 4 loop 5 if i > 10000000 6 then 7 exit; 8 end if; 9 insert into test02 values(i,'euvcg'); 10 i:=i+1; 11 end loop; 12 commit; 13 end; 14 / PL/SQL procedure successfully completed Executed in 185.125 seconds --創建索引 SQL> create index test02_idx on test02 (id,name); Index created Executed in 17.172 seconds --分析表 SQL> exec dbms_stats.gather_table_stats('LIJIAMAN','TEST02'); PL/SQL procedure successfully completed Executed in 3.921 seconds SQL> analyze table test02 compute statistics; Table analyzed Executed in 39.11 seconds --查看分析結果 SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST02'; TABLE_NAME BLOCKS EMPTY_BLOCKS ------------------------------ ---------- ------------ TEST02 23357 195 Executed in 0.078 seconds SQL> select 2 ds.segment_name, 3 ds.segment_type, 4 ds.header_file, 5 ds.header_block, 6 ds.bytes, 7 ds.blocks, 8 ds.extents 9 from 10 dba_segments ds 11 where 12 ds.segment_name = 'TEST02'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS ------------- ------------------ ----------- ------------ ---------- ---------- ---------- TEST02 TABLE 6 130 192937984 23552 94 Executed in 0.078 seconds
可以看到。test02一共占用了94個extents,23552個數據塊。其中23357個數據塊有數據,195個數據塊空閑。
接下來,我們先查看表的信息,這里截取了部分結果。在這里,我們需要了解ROWID的作用,rowid是數據在oracle儲存中的具體位置,1-6位為object id,7-9位為file_id,10-15位代表block id,16-18位為row number。在下面結果中,前5條數據在AAAACD塊中,后6條數據在AAAACE塊中。我們取出一個block,查看其數據:
SQL> select * from test02 where rowid like 'AAASNnAAGAAAACM%'; ID NAME ---------- --------------- 2912 euvcg 2913 euvcg 2914 euvcg 2915 euvcg ... ... 3394 euvcg 3395 euvcg 484 rows selected
(2)刪除test02的一半數據,數據塊並沒有釋放,執行shrink操作
--刪除500萬條數據 SQL> declare 2 i number :=1; 3 begin 4 loop 5 if i > 10000000 6 then 7 exit; 8 end if; 9 delete test02 where id = i; 10 i:=i+2; 11 end loop; 12 commit; 13 end; 14 / --經過查看,數據塊未釋放 --激活行移動 SQL> alter table test02 enable row movement; Table altered Executed in 0.078 seconds --執行shrink操作 SQL> alter table test02 shrink space cascade; Table altered Executed in 234.593 seconds
需要注意的是,在執行shrink的過程中,在表上是有鎖存在的,在表上存在3級鎖(SX)
SQL> select * from v$lock where type in ('TM','TX'); SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK --- ---- ---------- ---------- ---------- ---------- ---------- ---------- 30 TM 74597 0 3 0 178 0 30 TX 327684 1294 6 0 0 0 30 TX 327699 994 6 0 178 0
(3)分析數據,查看表信息
SQL> analyze table test02 compute statistics; Table analyzed SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST02'; TABLE_NAME BLOCKS EMPTY_BLOCKS ---------- ---------- ------------ TEST02 11648 152 SQL> select 2 ds.segment_name, 3 ds.segment_type, 4 ds.header_file, 5 ds.header_block, 6 ds.bytes, 7 ds.blocks, 8 ds.extents 9 from 10 dba_segments ds 11 where 12 ds.segment_name = 'TEST02'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS ------------- ------------------ ----------- ------------ ---------- ---------- ---------- TEST02 TABLE 6 130 96665600 11800 83
在執行shrink之后,我們的數據塊使用量由原來的23552減少為11800。
(4)再次查看上面數據塊中的數據,可以看出在執行了shrink之后,該數據塊中的數據發生了變化。對於該塊,原來的數據保持不變,但是在已經刪除數據的空間中,有其它塊的數據插入了進來。
SQL> select * from test02 where rowid like 'AAASNnAAGAAAACM%'; ID NAME ---------- --------------- 2912 euvcg 4050 euvcg 2914 euvcg 4052 euvcg 2916 euvcg 4054 euvcg 3388 euvcg 3390 euvcg 3392 euvcg 3394 euvcg 399 rows selected
(9.3)結論
1.shrink是對行數據進行移動。對表進行shrink后,部分行數據的rowid發生了變化,而table所位於的block區域的位置卻沒有發生變化;
2.shrink產生TM(SX)鎖及TX鎖。
(9.4)對shrink有了一定的了解,我們再來看一下move
--創建表 create table test03 ( id number, name varchar(15) ); --插入數據 SQL> declare 2 i number :=1; 3 begin 4 loop 5 if i > 10000 6 then 7 exit; 8 end if; 9 insert into test03 values(i,'euvcg'); 10 i:=i+1; 11 end loop; 12 commit; 13 end; 14 / PL/SQL procedure successfully completed --統計信息 SQL> analyze table test03 compute statistics; Table analyzed --查看統計信息 SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST03'; TABLE_NAME BLOCKS EMPTY_BLOCKS ------------------------------ ---------- ------------ TEST03 28 4 SQL> select 2 ds.segment_name, 3 ds.segment_type, 4 ds.header_file, 5 ds.header_block, 6 ds.bytes, 7 ds.blocks, 8 ds.extents 9 from 10 dba_segments ds 11 where 12 ds.segment_name = 'TEST03'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS ------------ ------------------ ----------- ------------ ---------- ---------- ---------- TEST03 TABLE 6 146 262144 32 4
取其中一個數據塊,查看存儲的信息
SQL> select rowid,id,name from test03 where rowid like 'AAASNxAAGAAAACY%'; ROWID ID NAME ------------------ ---------- --------------- AAASNxAAGAAAACYAAA 3880 euvcg AAASNxAAGAAAACYAAC 3882 euvcg AAASNxAAGAAAACYAAE 3884 euvcg AAASNxAAGAAAACYAAG 3886 euvcg AAASNxAAGAAAACYAAI 3888 euvcg AAASNxAAGAAAACYAAK 3890 euvcg AAASNxAAGAAAACYAAM 3892 euvcg AAASNxAAGAAAACYAAO 3894 euvcg AAASNxAAGAAAACYAAQ 3896 euvcg
… … …
執行move操作
SQL> alter table test03 move; Table altered SQL> analyze table test03 compute statistics; Table analyzed SQL> select 2 dt.table_name, 3 dt.blocks, 4 dt.empty_blocks 5 from 6 dba_tables dt 7 where 8 dt.table_name = 'TEST03'; TABLE_NAME BLOCKS EMPTY_BLOCKS ------------------------------ ---------- ------------ TEST03 14 2 SQL> select 2 ds.segment_name, 3 ds.segment_type, 4 ds.header_file, 5 ds.header_block, 6 ds.bytes, 7 ds.blocks, 8 ds.extents 9 from 10 dba_segments ds 11 where 12 ds.segment_name = 'TEST03'; SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS -------------- ------------------ ----------- ------------ ---------- ---------- ---------- TEST03 TABLE 6 186 131072 16 2
在move之前我們查看了數據塊AAASNxAAGAAAACY的信息,一共有242行,在move之后,我們再去查看該數據塊,發現沒有數據存在。經過查看,id=4340的行信息之前存在該數據塊,我們可以去看一下目前該行數據存在哪個數據塊,找到新的數據塊之后查看數據。
--查看了數據塊AAASNxAAGAAAACY的信息,發現沒有數據,說明數據已經轉移到新的數據塊中去了 SQL> select rowid,id,name from test03 where rowid like 'AAASNxAAGAAAACY%'; ROWID ID NAME ------------------ ---------- --------------- --先前的數據塊中存在id=4340這一行數據,我們看一下該行數據目前的rowid SQL> select rowid,id,name from test03 where id=4340; ROWID ID NAME ------------------ ---------- --------------- AAASNyAAGAAAAC9AHf 4340 euvcg --通過rowid,我們可以確定該行數據的新的數據塊id,查詢該數據塊信息 SQL> select rowid,id,name from test03 where rowid like 'AAASNyAAGAAAAC9%'; ROWID ID NAME ------------------ ---------- --------------- ... ... ... AAASNyAAGAAAAC9ADz 480 euvcg AAASNyAAGAAAAC9AD0 482 euvcg AAASNyAAGAAAAC9AD1 484 euvcg AAASNyAAGAAAAC9AD2 486 euvcg AAASNyAAGAAAAC9AD3 488 euvcg AAASNyAAGAAAAC9AD4 490 euvcg AAASNyAAGAAAAC9AD5 3880 euvcg AAASNyAAGAAAAC9AD6 3882 euvcg AAASNyAAGAAAAC9AD7 3884 euvcg AAASNyAAGAAAAC9AD8 3886 euvcg AAASNyAAGAAAAC9AD9 3888 euvcg AAASNyAAGAAAAC9AD+ 3890 euvcg AAASNyAAGAAAAC9AD/ 3892 euvcg ... ... ...
結論:1.move之后,與先前數據塊信息進行對比,發現數據塊信息發生了改變,數據已經移到了其它數據塊中。多個數據塊的信息合並到了同一個數據塊,但是數據的順序並沒有發生改變,即數據在原塊中的順序是怎么樣的,遷移到新數據塊中還是這樣的;
2.move之后,數據塊的使用量減少了,說明move收縮空間,降低高水位;
參考文檔:http://docs.oracle.com/cd/E11882_01/server.112/e40540/logical.htm#CNCPT89026
Oracle運維最佳實踐-上