欢迎投稿

今日深度:

浅析ORACLE数据库高水位线(highwatermark)

浅析ORACLE数据库高水位线(highwatermark)


ORACLE数据库逻辑结构包括:数据库块(block),扩展(extent 区),段(segment),表空间(tablespace)。高水位线就存在于段(segment)中,它用于标识段中已使用过的数据块与未使用地的数据块二者间交界,扫描表数据的时候,高水位线以下的所有数据块都必须被扫描。

首先需要提醒大家,高水位线存在于段,且高水位线的位置记录在段头,也就是段的第一个数据块中。因此,我们可以转存储段头信息来看高水位信息。

段又有很多种,数据段,索引段,临时段,回滚段等。当创建段的时候会分配区,区是由若干个物理连续的数据块组成。区的分配是需要初始化数据块的,默认初始化(format)单位为1M。记住,高水位线并不是初始化的交界片,被初始化过的数据库并不一定使用过。

以下通过实验来进一步阐述高水位线:

创建测试表

SQL> create table hwm as select * from dba_segments;

Table created.

SQL> BEGIN
DBMS_STATS.gather_table_stats('SYS','HWM');
END;
2 3 4
5 /

PL/SQL procedure successfully completed.

SQL> select HEADER_FILE,HEADER_BLOCK from DBA_SEGMENTS where SEGMENT_NAME='HWM'
;

HEADER_FILE HEADER_BLOCK
----------- ------------
1 89168

SQL> ALTER SYSTEM DUMP DATAFILE 1 BLOCK 89168;

Extent Header:: spare1: 0 spare2: 0 #extents: 13 #blocks: 103
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x00415cb5 ext#: 12 blk#: 5 ext size: 8
#blocks in seg. hdr's freelists: 0
#blocks below: 100
mapblk 0x00000000 offset: 12

删除3000行数据提交修改,再看看高水位线有没有变化:

SQL> delete from hwm where rownum < 3000;

2999 rows deleted.

SQL> commit;

Commit complete.

SQL> alter system checkpoint;

System altered.

SQL> ALTER SYSTEM DUMP DATAFILE 1 BLOCK 89168;

Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 13 #blocks: 103
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x00415cb5 ext#: 12 blk#: 5 ext size: 8
#blocks in seg. hdr's freelists: 0
#blocks below: 100
mapblk 0x00000000 offset: 12

并没有发现高水位线有变化,那么插入2000行继续观察

SQL> insert into hwm select * from dba_segments where rownum < 2001;

2000 rows created.

SQL> commit;

Commit complete.

SQL> alter system checkpoint;

System altered.

SQL> ALTER SYSTEM DUMP DATAFILE 1 BLOCK 89168;

System altered.

Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 13 #blocks: 103
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x00415cb5 ext#: 12 blk#: 5 ext size: 8
#blocks in seg. hdr's freelists: 0
#blocks below: 100
mapblk 0x00000000 offset: 12
Unlocked
Map Header:: next 0x00000000 #extents: 13 obj#: 84253 flag: 0x40000000

高水位线并没有发生变化,说明高水位线以下的delete过的数据块是可以被复用的.

此时如果再插入1000行,高水位线应该是会变化的,求证一下:

SQL> insert into hwm select * from dba_segments where rownum < 1001;

1000 rows created.

SQL> commit;

Commit complete.

SQL> alter system checkpoint;

System altered.

SQL> ALTER SYSTEM DUMP DATAFILE 1 BLOCK 89168;

System altered.

Extent Header:: spare1: 0 spare2: 0 #extents: 13 #blocks: 103
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x00415cb5 ext#: 12 blk#: 5 ext size: 8
#blocks in seg. hdr's freelists: 3
#blocks below: 100
mapblk 0x00000000 offset: 12
Unlocked
Map Header:: next 0x00000000 #extents: 13 obj#: 84254 flag: 0x40000000

发现高水位线依旧没有改变,继续插入新数据并观察:

SQL> insert into hwm select * from dba_segments where rownum < 1001;

1000 rows created.

SQL> commit;

Commit complete.

SQL> alter system checkpoint;

System altered.

SQL> ALTER SYSTEM DUMP DATAFILE 1 BLOCK 89168;

System altered.

Extent Header:: spare1: 0 spare2: 0 #extents: 15 #blocks: 119
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x00415cc5 ext#: 14 blk#: 5 ext size: 8
#blocks in seg. hdr's freelists: 1
#blocks below: 116
mapblk 0x00000000 offset: 14
Unlocked
Map Header:: next 0x00000000 #extents: 15 obj#: 84254 flag: 0x40000000

以上可以看到,delete并不能回收表数据,在增删改表数据库的过程使得高水位线持续增长,且被删除的数据记录位置也无法100%复用,因此难免会存在碎片。比如,一张表100万数据,将全表数据delete之后,高水位线位置依旧在第100万行处,尽管此时表数据为0行,但全表扫描时候仍然需要扫描所有已使用过的数据块,全表扫描的效率将越来越低下。

因此oracle也提供了多种回收高水位线的方法,诸如:

表重建, 如CATS(create table as select ...)

导出导入(exp/imp,expdp/impdp)

truncate(危险,因此慎用)

shrink space

move table

DBMS_REDEFINITION表在线重定义

等等 

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

本文来自于我的技术博客 http://blog.csdn.net/robo23

转载请标注源文链接,否则追究法律责任!

www.htsjk.Com true http://www.htsjk.com/oracle/22433.html NewsArticle 浅析ORACLE数据库高水位线(highwatermark) ORACLE数据库逻辑结构包括:数据库块(block),扩展(extent 区),段(segment),表空间(tablespace)。 高水位线就存在于段(segment)中,它用于标识段中已...
评论暂时关闭