oracle的高水位线HWM

当我们创建一个表的时候,在还没有为这张表插入数据时,oracle默认会分配8个块给新建表。如下我们新建一张表t1:
SYS@orcl 25-SEP-14>create table t1 as select * from dba_objects where 1=2;

Table created.
然后再查询oracle为这张表分配了多大的空间:
SYS@orcl 25-SEP-14>select segment_name,segment_type,blocks from user_segments where segment_name='T1';

SEGMENT_NAME                                                                      SEGMENT_TYPE           BLOCKS
--------------------------------------------------------------------------------- ------------------ ----------
T1                                                                                TABLE                       8
随着业务的增长我们会往这张表里插入大量的数据,高水位线就是一个段内的标记,用来说明还有多少没使用的块可以分配给这个segment。通常情况下,高水位线的增长幅度是一次5个数据块。原则上高水位线只能增大不能缩小,即使将表中的数据全部delete掉,高水位线还是会保持原来的位置,因为这样,所以即使我们将表中的大部分数据删除了,在进行查询操作的时候还是会进行全段扫描,全表扫描通常要读出直到高水位线标记的所有的属于该表的数据块,这样会大大降低查询性能。另外当我们往表中插入记录的时候,使用的是高水位线以上的数据块,此时高水位线又会增长。
以下是处理高水位线的方法:
1.将表进行重建,使用语句alter table table_name move tablespace tablespace_name;
注意,使用了这个语句之后,原表上的索引也会无效,因此执行完以上语句之后要对表中的索引进行重建。
2.执行alter table table_name shrink space;
这是oracle10g引入的新性能,注意,在执行这条语句之前,先要允许行移动,alter table table_name enable row movement;
move是通过移动数据来降低hwm,需要更多的磁盘空间,而shrink是通过delete和insert,会产生较多的undo和redo。
move的效率相对于shrink来说要高一些,但是会导致索引失效。
3.重建表
复制要保留的数据到临时表t_tmp,drop原表,然后rename临时表t_tmp为原表,注意重建过程需要备份该表的触发器和存储过程等语法。
4.逻辑导入导出
5.alter table table_name deallocate unused;
deallocate unused会hwm上面未使用的空间,但是并不会释放hwm下面的自由空间,也不会移动hwm的位置。
6.truncate table

下面我们以第一种方式move为例看看如何处理高水位线:
刚刚我们创建了一张表结构和dba_objects一样的表t1,现在做如下相关查询:


SYS@orcl 25-SEP-14>select segment_name,segment_type,blocks from user_segments where segment_name='T1';

SEGMENT_NAME                                                                      SEGMENT_TYPE           BLOCKS
--------------------------------------------------------------------------------- ------------------ ----------
T1                                                                                TABLE                       8

往表中插入足够多的数据:
SYS@orcl 25-SEP-14>insert /*+ APPEND NOLOGGING */ into t1 select * from dba_objects;

72602 rows created.

SYS@orcl 25-SEP-14>commit;

Commit complete.

SYS@orcl 25-SEP-14>select max(object_id) from t1;

MAX(OBJECT_ID)
--------------
         75306
SYS@orcl 25-SEP-14>insert /*+ APPEND NOLOGGING */ into t1 select 
  2  owner,object_name,subobject_name,object_id+75306,data_object_id,object_type,created,last_ddl_time,timestamp,status,temporary,generated,secondary,
  3  namespace,edition_name from t1;

72602 rows created.

SYS@orcl 25-SEP-14>commit;

Commit complete.

创建索引:
SYS@orcl 25-SEP-14>create unique index idx_objectid on t1(object_id) tablespace users;

Index created.

SYS@orcl 25-SEP-14>create index idx_index02 on t1(owner,object_name) tablespace users;

Index created.
查看索引信息:
SYS@orcl 25-SEP-14>select index_name,status from user_indexes where table_name='T1';

INDEX_NAME                     STATUS
------------------------------ --------
IDX_INDEX02                    VALID
IDX_OBJECTID                   VALID

再次查看表的信息:
SYS@orcl 25-SEP-14>select segment_name,segment_type,blocks from user_segments where segment_name='T1';


SEGMENT_NAME                                                                      SEGMENT_TYPE           BLOCKS
--------------------------------------------------------------------------------- ------------------ ----------
T1                                                                                TABLE                    2176

SYS@orcl 25-SEP-14>select table_name,num_rows,blocks,empty_blocks from user_tables where table_name='T1';

TABLE_NAME                       NUM_ROWS     BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T1
可以看到这里的记录为空,这是因为没有做统计分析:
SYS@orcl 25-SEP-14>exec dbms_stats.gather_table_stats(user,'T1');

PL/SQL procedure successfully completed.

SYS@orcl 25-SEP-14>select table_name,num_rows,blocks,empty_blocks from user_tables where table_name='T1';


TABLE_NAME                       NUM_ROWS     BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T1                                 145204       2068            0
这里看到empty_blocks的信息仍为空,这是因为这个字段只有通过analyze收集统计信息之后才会有数据:
SYS@orcl 25-SEP-14>analyze table t1 compute statistics;

Table analyzed.

SYS@orcl 25-SEP-14>select table_name,num_rows,blocks,empty_blocks from user_tables where table_name='T1';


TABLE_NAME                       NUM_ROWS     BLOCKS     EMPTY_BLOCKS
------------------------------          ----------          ----------     ------------
T1                                          145204               2068             107

SYS@orcl 25-SEP-14>select   2068 +  107 from dual;

2068+107
----------
      2175
(这里和前面的2176相比少了一个块,那一个块是用来存储segment信息的)

下面我们delete表中的数据,留下两行:
SYS@orcl 25-SEP-14>delete from t1 where rownum<=145202;

145202 rows deleted.

SYS@orcl 25-SEP-14>select count(*) from t1;

COUNT(*)
----------
         2
再次查看表信息:
SYS@orcl 25-SEP-14>select segment_name,segment_type,blocks from user_segments where segment_name='T1';


SEGMENT_NAME                                                                      SEGMENT_TYPE           BLOCKS
--------------------------------------------------------------------------------- ------------------ ----------
T1                                                                                TABLE                    2176


SYS@orcl 25-SEP-14>select table_name,num_rows,blocks,empty_blocks from user_tables where table_name='T1';


TABLE_NAME                       NUM_ROWS     BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T1                                 145204       2068          107

可以看出高水位线并没有发生任何变化。下面使用move来处理高水位线:
SYS@orcl 25-SEP-14>alter table t1 move tablespace hh;

Table altered.

查看索引状态已变为unusable,重建索引:
SYS@orcl 25-SEP-14>select index_name,status from user_indexes where table_name='T1';

INDEX_NAME                     STATUS
------------------------------ --------
IDX_INDEX02                    UNUSABLE
IDX_OBJECTID                   UNUSABLE

SYS@orcl 25-SEP-14>alter index IDX_INDEX02 rebuild;

Index altered.

SYS@orcl 25-SEP-14>alter index IDX_OBJECTID rebuild;

Index altered.

SYS@orcl 25-SEP-14>select index_name,status from user_indexes where table_name='T1';

INDEX_NAME                     STATUS
------------------------------ --------
IDX_INDEX02                    VALID
IDX_OBJECTID                   VALID

重新进行统计分析,查看表信息:
SYS@orcl 25-SEP-14> analyze table t1 compute statistics;

Table analyzed.
SYS@orcl 25-SEP-14>select segment_name,segment_type,blocks from user_segments where segment_name='T1';


SEGMENT_NAME                                                                      SEGMENT_TYPE           BLOCKS
--------------------------------------------------------------------------------- ------------------ ----------
T1                                                                                TABLE                       8


SYS@orcl 25-SEP-14>select table_name,num_rows,blocks,empty_blocks from user_tables where table_name='T1';


TABLE_NAME                       NUM_ROWS     BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
T1                                      2          4            4

说明此时高水位线已经降低了。
请使用浏览器的分享功能分享到微信等