所有的Oracle表都有一个容纳数据的上限(很像一个水库历史最高的水位),我们把这个上限称为“High water mark"或HWM。这个HWM是一个标记(专门有一个数据块来记录高水标记等),用来说明已经有多少数据块分配给这个表。HWM通常增长的幅度为一次5个数据块。
通常,我们在表空间中创建一张表时,Oracle就会初始分配一些blocks/extents给该表,之后,随着表中数据量的增加,也会相应的给表自动分配blocks/extents。
SQL>select blocks,empty_blocks,num_wors,from dba_tables where table_name=‘HWM_TEST‘;
103 9 8000 -->表HWM_TEST占用了103个block,9个block未使用,有8000行记录。
SQL>select blocks,extents,header_block from dba_segments where segment_name=‘HWM_TEST‘;
BLOCKS EXTENTS HEADER_BLOCK
---------- ---------- ------------
112 14 83 -->Oracle总共为表HWM_TEST分配了112个block,14个extent,段头(Segment Header)所在块是83号。
SQL>delete from hwm_test where rownum < 3001; -->删除部分数据。
3000 rows deleted.
SQL>commit;
Commit complete. -->提交。
现在我们再查询DBA_TABLES、DBA_SEGMENTS时,统计数据是没有任何变动的,需要分析一下:
SQL>analyze table hwm_test compute statistics;
Table analyzed.
SQL>select blocks,empty_blocks,num_rows from dba_tables where table_name=‘HWM_TEST‘;
BLOCKS EMPTY_BLOCKS NUM_ROWS
---------- ------------ ----------
103 9 5000 -->经过analyze后,发现统计的记录数发生了变化,可数据块的数量并没有变化。
SQL>select blocks,extents,header_block from dba_segments where segment_name =‘HWM_TEST‘;
BLOCKS EXTENTS HEADER_BLOCK
---------- ---------- ------------
112 14 83
那如何确定表HWM_TEST究竟使用了多少个block呢?可以通过ROWID的来查询:
SQL>select count(distinct dbms_rowid.rowid_block_number(rowid)) "Used Blocks" from HWM_TEST;
Used Blocks
-----------
63
那现在可以明白:Oracle分配了112个block给HWM_TEST表,其中有103个数据块保存用户数据,但实际上是有63个block是实际用户数据占用的block数。
降低高水线有多种方法:EXP/IMP、TRUNCATE或者使用MOVE,在10G,Oracle提供了shrink功能。使用哪种方法因人而异且需要根据实际情况,一般情况我习惯使用MOVE和SHRINK。
1、使用alter table ... shrink space
SQL>alter table HWM_TEST enable row movement;
Table altered. -->这是必须的步骤, 即将收缩(shrink)的数据表,必须启用row movement。
SQL>alter table HWM_TEST shrink space;
Table altered. -->这就是收缩空间语句的庐山真面目,当然还可以加其他参数,如加级联(cascade),就会把相应的索引段也进行收缩。
SQL>analyze table HWM_TEST compute statistics;
Table analyzed. -->再次分析表HWM_TEST。
SQL>select blocks,empty_blocks,num_rows from dba_tables where table_name=‘HWM_TEST‘;
BLOCKS EMPTY_BLOCKS NUM_ROWS
---------- ------------ ----------
63 9 5000 -->现在BLOCKS值变为63了。
2、使用alert table ... move
SQL>select blocks,empty_blocks,num_rows from dba_tables where table_name=‘HWM_TEST‘;
BLOCKS EMPTY_BLOCKS NUM_ROWS
---------- ------------ ----------
70 2 3001
SQL>alter table hwm_test move;
Table altered.
SQL>analyze table hwm_test compute statistics;
Table analyzed.
SQL>select blocks,empty_blocks,num_rows from dba_tables where table_name=‘HWM_TEST‘;
BLOCKS EMPTY_BLOCKS NUM_ROWS
---------- ------------ ----------
43 5 3001
使用alter table ... shrink space/move均可收缩表的高水线