分类: Oracle
2010-03-01 19:30:54
Shrink如何重置空块?
Shrink与Move的差异在哪里?
相信用实例来解释比较好一点:
Code:
SQL> create table t ( x number )
2 tablespace users
3 storage ( initial
4 /
Table created.
建表完成。
SQL> analyze table t compute statistics;
Table analyzed.
分析表完成。
SQL> select blocks, extents from user_segments where segment_name = 'T';
BLOCKS EXTENTS
---------- ----------
1280 10
查看该表占用的块和区。
SQL> select blocks, empty_blocks from user_tables where table_name = 'T';
BLOCKS EMPTY_BLOCKS
---------- ------------
0 1280
查看已用块与空块。新建表,所以一块也没有用上。
建表初始指定10mb分配,换算成1280个块和10个区。从这里可看到:
——用户段中分配给表T共1280个块
——这些块都没有格式化以备接收数据
然后我们插入数据:
Code:
SQL> insert into t
2 select rownum
3 from dual
4 connect by level <= 100000;
100000 rows created.
插了10万行。
SQL> analyze table t compute statistics;
Table analyzed.
再分析一次得到最新的统计数据。
SQL> select blocks, extents from user_segments where segment_name = 'T';
BLOCKS EXTENTS
---------- ----------
1280 10
再得到准确的块数据与区数据。此时没变化。
SQL> select blocks, empty_blocks from user_tables where table_name = 'T';
BLOCKS EMPTY_BLOCKS
---------- ------------
186 1094
插了10万行数据,可以看到已经分配的数据块与区数量没有任任变化,但空块变小,是186块。
186 块位置就是现在的HWM, 因为这186块是已经格式化过随时待命以备接收数据。而186以上的块则是没格过也暂不准备接收数据的块.
empty_blocks nor it will lower the blocks that are formatted to receive data (that is, the HWM).
现在我们删除一些数据,可看是既不增加空块数量也不减少已格过准备接收数据的块。
Code:
SQL> delete from t where rownum <= 90000;
90000 rows deleted.
一下子删掉9万行。
SQL> analyze table t compute statistics;
Table analyzed.
再分析一下表。
SQL> select blocks, empty_blocks from user_tables where table_name = 'T';
BLOCKS EMPTY_BLOCKS
---------- ------------
186 1094
Code:
SQL> select count(distinct dbms_rowid.rowid_block_number(rowid)) used_blocks from t;
USED_BLOCKS
-----------
16
然而186块中有数据的块只有16块,余下的块属于freelist用于insert/update。
现在我们将move这个表来展示它如何调整HWM.
Code:
SQL> alter table t move tablespace users;
Table altered.移动完成。
SQL> analyze table t compute statistics;
Table analyzed.分析完成。
SQL> select blocks, empty_blocks from user_tables where table_name = 'T';
BLOCKS EMPTY_BLOCKS
---------- ------------
20 1260
可以看到Move是将HWM收缩下来了,从186降到了20,并增加了空块数量,但是再往下看:
Code:
SQL> select blocks, extents from user_segments where segment_name = 'T';
BLOCKS EXTENTS
---------- ----------
1280 10
Now, to *reclaim* that space we will use shrink.
这又告诉我们Move并没有收缩段中占有的空块(即这一步段空间占用并没有下来)。在操作系统级上面,空间也没有任何的收缩。现在我们用shrink来回收这些空间。
Code:
SQL> alter table t enable row movement;
Table altered.
先令该表行可被移动。
SQL> alter table t shrink space;
Table altered.
再shrink它。
SQL> analyze table t compute statistics;
Table analyzed.
再分析表。
SQL> select blocks, extents from user_segments where segment_name = 'T';
BLOCKS EXTENTS
---------- ----------
128 1
此时我们可以看到。只占用了128个块和1个区(10M)。
SQL> select blocks, empty_blocks from user_tables where table_name = 'T';
BLOCKS EMPTY_BLOCKS
---------- ------------
20 108
再看已用块与空块。可以看到空块是108,已用块为20块。
SQL>
那么现在可以看到该表真实地从占用1280块及10个区的情况下,收缩到了最小状态:128块和1个区。
希望以上能真正解释大家的疑问。