ITPub博客

首页 > 数据库 > Oracle > Oracle 之HWM

Oracle 之HWM

原创 Oracle 作者:静以致远√团团 时间:2014-07-28 18:35:08 0 删除 编辑

Oracle HWM

什么是HWM

所有的oracle segments都有一个在段内容纳数据的上限,我们把这个上限称为HWM(High Water Mark)。这个HWM是一个标记,用来说明已经有多少没有使用的数据块分配给这个segment。HWM通常增长的幅度为一次5个数据块,原则上HWM只会增大,不会缩小,即使将表中的数据全部删除,HWM还是为原值,由于这个特点,使HWM很象一个水库的历史最高水位,这也就是HWM的原始含义,当然不能说一个水库没水了,就说该水库的历史最高水位为0。但是如果我们在表上使用了truncate命令,则该表的HWM会被重新置为0。

在手动段空间管理(Manual Segment Space Management)中,段中只有一个HWM,但是在Oracle9i添加的自动段空间管理(Automatic Segment Space Management)中,当数据插入以后,如果是插入到新的数据块中,数据块就会被自动格式化等待数据访问。而在自动段空间管理中,数据插入到新的数据块以后,数据块并没有被格式化,而是在第一次在第一次访问这个数据块的时候才格式化这个块。所以又多出一条水位线,用来标示已经被格式化的块。这条水位线就叫做低HWM。一般来说,低HWM肯定是低于等于HWM。

HWM的影响

HWM的用途

在使用select语句会对表中的数据进行一次扫描,Oracle会扫描高水位线以下的数据块。也就是说新建的一张表,进行了一次select操作,那么由于高水位线HWM在最低的0位置上,所以没有数据块需要被扫描,扫描时间会极短。如果该表中已经被插入大量的数据,随后这些数据被delete。由于插入了数据,由于delete语句不影响高水位线,所以这个时候的高水位线就在这些数据这里。这个时候再一次用select语句进行扫描,虽然这个时候表中没有数据,但是由于扫描是按照高水位线来的,需要把这些数据的存储空间都要扫描一次。 HWM数据库的操作有如下影响

1、全表扫描通常要读出直到HWM标记的所有的属于该表数据库块,即使该表中没有任何数据。

2、即使HWM以下有空闲的数据库块,键入在插入数据时使用了append关键字,则在插入时使用HWM以上的数据块,此时HWM会自动增大。

测试一下

创建一个测试表

SQL> create table test(id number(4,0),test varchar2(10)) tablespace users;

Table created.

此时表中没有数据,通过user_tables和user_segments来查看一下表中数据块的使用情况

SQL> col segment_name for a20

SQL> select segment_name,segment_type,blocks,bytes from user_segments where segment_name='TEST';


SEGMENT_NAME         SEGMENT_TYPE           BLOCKS      BYTES

-------------------- ------------------ ---------- ----------

TEST                 TABLE                       8      65536

这里的BLOCKS指的是该表初始化segment的大小


使用analyze 收集统计信息


SQL> analyze table test compute statistics;

Table analyzed.

SQL> select table_name,num_rows,blocks,empty_blocks from user_tables where table_name='TEST';


TABLE_NAME        NUM_ROWS     BLOCKS EMPTY_BLOCKS

--------------- ---------- ---------- ------------

TEST                     0          0            8

也就是说现在分给给test表的8个数据库都处于空闲状态

插入测试数据

SQL> begin

2  for i in 1..10000 loop

3  insert into test

4  values(round(dbms_random.value(0,10000)),dbms_random.string('u',5));

5  end loop;

6  commit;

7  end;

8  /


PL/SQL procedure successfully completed.

SQL> select count(*) from test;

COUNT(*)

----------

10000


再次查看此时的segment分配信息,已经非配32个block

SQL> select segment_name,segment_type,blocks from user_segments where segment_name='TEST';


SEGMENT_NAME         SEGMENT_TYPE           BLOCKS

-------------------- ------------------ ----------

TEST                 TABLE                      32


SQL> analyze table test compute statistics;

Table analyzed.


SQL> select table_name,blocks,empty_blocks from user_tables where table_name='TEST';

TABLE_NAME          BLOCKS EMPTY_BLOCKS

--------------- ---------- ------------

TEST                    28            4

segment和tables中的block对应关系如下

user_segment.blocks=user_tables.blocks+user_tables.empty_blocks+1

其中

user_tables.blocks列代表该表中曾经使用过得数据库块的数目,即水线。 

user_tables.empty_blocks代表分配给该表,但是在水线以上的数据库块,即从来没有使用的数据块。

1是指多出的一个数据块用保留来做segment header

使用delete 删除表中数据,将会发现表中数据的水线并未降低

SQL> delete from test;

10000 rows deleted.


SQL> commit;

Commit complete.


SQL> select segment_name,segment_type,blocks from user_segments where segment_name='TEST';


SEGMENT_NAME         SEGMENT_TYPE           BLOCKS

-------------------- ------------------ ----------

TEST                 TABLE                      32


SQL> analyze table test compute statistics;

Table analyzed.


SQL> select table_name,blocks,empty_blocks from user_tables where table_name='TEST';

TABLE_NAME          BLOCKS EMPTY_BLOCKS

--------------- ---------- ------------

TEST                    28            4


使用shrink收缩表

SQL> alter table test enable row movement;

Table altered.


SQL> alter table test shrink space cascade;

Table altered.


SQL> select segment_name,segment_type,blocks from user_segments where segment_name='TEST';


SEGMENT_NAME         SEGMENT_TYPE           BLOCKS

-------------------- ------------------ ----------

TEST                 TABLE                       8


SQL> analyze table test compute statistics;


Table analyzed.


SQL> select table_name,blocks,empty_blocks from user_tables where table_name='TEST';


TABLE_NAME          BLOCKS EMPTY_BLOCKS

--------------- ---------- ------------

TEST                     1            7


回收HWM

1、使用move移动表

SQL> alter table test move;


Table altered.


SQL> alter table test move tablespace users;

Table altered.

2、如上面测试中的方法,使用shrink来收缩表

3、可以的情况下重建表 

4、使用alter  table table_name deallocate unused

DEALLOCATE UNUSED为释放HWM上面的未使用空间,但是并不会释放HWM下面的自由空间,也不会移动HWM的位置.

5、不重要的数据被删除,或者确定该表中数据不需要闪回的情况下尽量使用truncate删除数据。



来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29320885/viewspace-1240343/,如需转载,请注明出处,否则将追究法律责任。

上一篇: 配置dns和apache
请登录后发表评论 登录
全部评论
每个人都有梦想,去实现吧!

注册时间:2013-11-14

  • 博文量
    164
  • 访问量
    2103642