概述

深入理解HWM对于做数据库优化是必须掌握的一个基础,很多时候我们以为删了数据后表应该会快很多,但是得到的结果却很不理想,这其中就涉及到HWM方面了,也是truncate和delete不同的地方。


一、什么是水线 (High Water Mark)?

所有的 oracle 段(segments,在此,为了理解方便,建议把 segment 作为表的一个同义词) 都有一个在段内容纳数据的上限,我们把这个上限称为"high water mark"或 HWM。这个 HWM是一个标记,用来说明已经有多少没有使用的数据块分配给这个 segment。

HWM 通常增长的幅度为一次5个数据块,原则上 HWM 只会增大,不会缩小,即使将表中的数据全部删除,HWM还是为原值。

HWM 很象一个水库的历史最高水位,这也就是 HWM 的原始含义,当然不能说一个水库没水了,就说该水库的历史最高水位为0。但是如果我们在表上使用了 truncate 命令,则该表的 HWM 会被重新置为0。




mysql 表 清高水位 mysql水位线_数据


HWM本身的信息是储存在段头.在段空间是手工管理方式时,ORACLE是通过FREELIST(一个单向链表)来管理段内的空间分配.在段空间是自动管理方式时(ASSM),ORACLE是通过BITMAP来管理段内的空间分配.


二、HWM 数据库的操作有如下影响:

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

据。

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


三、如何计算一个表的 HWM ?

1、首先对表进行分析:

ANALYZE TABLE ESTIMATE/COMPUTE STATISTICS;

2、计算HWM

SELECT blocks, empty_blocks, num_rows FROM user_tables WHERE table_name = ;

说明:

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

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

3、实例

1)查看表段

create table test_hwm2 as select * from dba_objects;

SELECT segment_name, segment_type, blocks FROM dba_segments WHERE segment_name='TEST_HWM2';


mysql 表 清高水位 mysql水位线_数据块_02


2) 分析表

ANALYZE TABLE TEST_HWM2 ESTIMATE STATISTICS;


mysql 表 清高水位 mysql水位线_在段过小oracle_03


3)计算HWM

SELECT table_name,num_rows,blocks,empty_blocks FROM user_tables WHERE table_name='TEST_HWM2';


mysql 表 清高水位 mysql水位线_oracle性能优化求生指南_04


总的块数是1275,没有使用的块是3,也就是TEST_HWM2的HWM为1275-3+1=1273

注意:

这里DBA_SEGMENTS.BLOCKS 表示分配给这个表的所有的数据库块的数目。USER_TABLES.BLOCKS 表示已经使用过的数据库块的数目。


四、Oracle 表段中的高水位线 HWM

在 Oracle 数据的存储中,可以把存储空间想象为一个水库,数据想象为水库中的水。水库中的水的位置有一条线叫做水位线,在Oracle中,这条线被称为高水位线(High-warter mark,HWM)。在数据库表刚建立的时候,由于没有任何数据,所以这个时候水位线是空的,也就是说 HWM 为最低值。当插入了数据以后,高水位线就会上涨,但是这里也有一个特性,就是如果你采用 delete 语句删除数据的话,数据虽然被删除了,但是高水位线却没有降低,还是你刚才删除数据以前那么高的水位。也就是说,这条高水位线在日常的增删操作中只会上涨,不会下跌。

下面我们来谈一下 Oracle 中 Select 语句的特性。Select 语句会对表中的数据进行一次扫

描,但是究竟扫描多少数据存储块呢,这个并不是说数据库中有多少数据,Oracle 就扫描

这么大的数据块,而是 Oracle 会扫描高水位线以下的数据块。

如果是一张刚刚建立的空表,你进行了一次 Select 操作,那么由于高水位线 HWM 在最低的0位置上,所以没有数据块需要被扫描,扫描时间会极短。而如果这个时候你首先插入了一千万条数据,然后再用 delete 语句删除这一千万条数据。由于插入了一千万条数据,所以这个时候的高水位线就在一千万条数据这里。后来删除这一千万条数据的时候,由于 delete 语句不影响高水位线,所以高水位线依然在一千万条数据这里。这个时候再一次用 select 语句进行扫描,虽然这个时候表中没有数据,但是由于扫描是按照高水位线来的,所以需要把一千万条数据的存储空间都要扫描一次,也就是说这次扫描所需要的时间和扫描一千万条数据所需要的时间是一样多的。


之前小编也写了个存储过程是专门来计算HWM的,大家也可以通过那个方法来计算,降低HWM可以使用rebuild、truncate、shrink、move等操作,后面会介绍下怎么通过move去降低HWM,感兴趣的朋友可以关注下!!


mysql 表 清高水位 mysql水位线_数据块_05