探究 Oracle 高水位对数据库性能影响

Posted 云和恩墨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了探究 Oracle 高水位对数据库性能影响相关的知识,希望对你有一定的参考价值。


陈龙

云和恩墨西区工程师


本文整理来自上周四晚云和恩墨大讲堂陈龙的分享:探究 Oracle 高水位对数据库性能影响。


“之所以分享这个学习内容,是因为在我曾经经历的一些优化项目中,遇到由于高水位导致 SQL访问性能下降的问题,这促使我想更深入的去理解:什么是高水位线? 高水位到底会带来哪些影响? 应该怎样更好的解决高水位带来的问题?”


在开始深入分析之前,让我们先来了解一下高水位线 HWM。


一. HWM 的基本原理 (概念)


在 Oracle 中,高水位线(High-warter mark, HWM)被用来形容数据块的使用位置,即说明那些块是已经被使用的,那些没有。在创建一个新的表(段)时,Oracle 就会为这个对象分配第一个区,这个区的第一个块在创建时就会被分配存储一些表头信息。


高水位的管理机制在 MSSM 和 ASSM 中不同,下面分别介绍这两种管理机制:

1手动段空间管理(MSSM)


在以往的手动段空间管理中(MSSM),高水位标记 HWM,一个段分成三部分,header block,used block(row data),unusedblock,其中 used block 和 unused block 之间的分界线就是高水位标记 HWM,当进行全表扫描的时候,会扫描到 HWM 下的所有数据块,即使 used block 中很多数据被删除了,全表扫描还是以HWM为准。当 insert 时,freelist 中如果没有发现空闲块,就会在 HWM 上找寻未用块,同时 HWM 会向上移动。但是需要注意,HWM 只会向上移动,不会自动收缩,即使 delete 大量数据,导致 HWM下有很多空闲块。如下图:


探究 Oracle 高水位对数据库性能影响

第一个区的第一个块就称为段头块 (SEGMENT HEADE),段头中储存了一些信息,其中 HWM 的信息就存储在此。此时,因为第一个区的第一块用于存储段头的一些信息,虽然没有存储任何实际的记录,但也算是被使用,此时 HWM 是位于第2个块。当我们不断插入数据到 PM_USER 后,第1个块已经放不下后面新插入的数据,此时,ORACLE 将使用高水位之上的块用于存储新增数据。


探究 Oracle 高水位对数据库性能影响

在向表里插入数据后,HWM 本身也向上移。也就是说,当我们不断插入数据时,HWM 会往不断上移。这样在 HWM 之下的块,就表示使用过的块,HWM 之上的就表示已分配但从未使用过的块。


探究 Oracle 高水位对数据库性能影响

当对表进行导出、导入,或者 move 操作后,此时相当于新表插入数据, HWM 就会重新回到使用块的真实水平上。


探究 Oracle 高水位对数据库性能影响

2自动段管理(ASSM)


在自动段管理(ASSM)中,利用位图来代替空闲列表,当会话向表插入数据时,数据库只格式一个单独的位图块,而不是像 MSSM 中那样,会预先格式化一组块。在ASSM表空间中,除了一个 HWM 外,还有一个低 HWM。在 MSSM 中,HWM 推进时,所有的块都会格式化并立即生效,这样 Oracle 就可以安全的读取这些块。但是对于 ASSM,当 HWM推进时,Oracle 并不会立即格式所有的块,只是在第一次使用的时候才会对这些块进行格式化。也就是说,在第一次使用的的时候,即进行 insert 操作时,数据会插入到块中的任意水位线,位于低水位线(LHMW)和高水位线(HHMW)之间。因此在这个区域的许多块就不会被格式化。


在一个 ASSM 段中的每个数据块可能为这些状态:


▶ 在 HWM 之上

这些块都是没有格式化,且没有被使用

▶ 在 HWM 之下

这些块会处于这些状态之一:

  • 已经分配,但是没有被格式化且没有被使用

  • 已经格式化且包含数据

  • 已经格式化,但是已经删除数据,块为空

 

下面来了解整个过程:

 探究 Oracle 高水位对数据库性能影响

如图所示,在没进行数据插入前,段中的所有数据块都是没有格式化的且没有被使用。


假设这个时候某会话将数据插入时,数据库会把数据写到任何可以利用的空间块中。如下图所示:


探究 Oracle 高水位对数据库性能影响


数据库也可能会选择 HWM 和低 HWM 之间的任何数据块,或者低 HWM 之下的任何可用的空间的块。注意低 HWM 位置,因为 HWM 之下的块只有在被使用的时候,才进行格式化,所以当存在数据扫描时,特别是全表扫描,Oracle 会读取到低 HWM 的位置。如下图所示:


探究 Oracle 高水位对数据库性能影响

 

如果某条会话将数据插入到某表中,但是在当前的 HWM 之下没有足够的可用空间,那么这个时候 Oracle 会推进 HWM,重新分配一组新的没有格式化的块。当 HWM 与低 HWM 之间的位置被填满时,HWM 会继续往前推进,而低 HWM 会相应的推进到旧的 HWM 位置中。以此类推,当数据库不断的插入数据,HWM 会持续往前推移,而低 HWM 会尾随其后,除非重建、或缩小该对象等,否则 HWM 从不往回退。


探究 Oracle 高水位对数据库性能影响

二. HWM 演示过程


原理描述完了,那么现在我们来测试一下,验证之前我们所描述的部分。

我们先从 MSSM 管理的方式开始:


探究 Oracle 高水位对数据库性能影响

新建一个表,然后存储分配较多的对象,


探究 Oracle 高水位对数据库性能影响


插入较多的数据,

探究 Oracle 高水位对数据库性能影响
现在来查询下全表扫描所花时间,


探究 Oracle 高水位对数据库性能影响

从执行计划来看,该查询走得时全表扫描,期间产生6278个物理读,30028个逻辑读。现在来分析该表,

探究 Oracle 高水位对数据库性能影响

查看统计信息,

探究 Oracle 高水位对数据库性能影响

从该表的统计信息来看,该表共有15384个块,其中没有用到的块有0个,共有1003089行。

 

现在来测试下 delete 对 hwm 的影响,


探究 Oracle 高水位对数据库性能影响

很奇怪的现象,这个表已经没有数据了,为什么查询时间还是和以前的差不多,其中逻辑读是 30532,比之前还多了。

 

现在再对该表进行分析,


探究 Oracle 高水位对数据库性能影响


从统计信息来看,该表使用的块还是15384个块,但是空余块依然是0个,按道理来说,在delete 后,应该会有空余的块才对。其中,这里可以看出行数已经变成了0。


从这里就可以验证了之前的说法,即 HWM 在插入数据时,当现有空间不足而进行空间的扩展时会向上移,但删除数据时不会往下移。这就会造成 ORACLE 的全表扫描是读取 HWM下的所有 BLOCK,也就是说,不管 HWM 下的 BLOCK 现在实际有没有存放数据,ORACLE 都会一一读取,这样,在 DELETE 表后,ORACLE 读了大量的空块,耗去了大量的时间。


测试环境没有 show_space 这个过程,现在声明它:


SQL>createorreplaceprocedure show_space

 2 ( p_segname_1 invarchar2,

 3 p_space invarchar2default'MANUAL',

 4 p_type_1 invarchar2default'TABLE',

 5 p_analyzed invarchar2default'N',

 6 p_owner_1 invarchar2defaultuser)

 7 as

 8 p_segname varchar2(100);

 9 p_type varchar2(10);

 10 p_owner varchar2(30);

 11 l_unformatted_blocks number;

 12 l_unformatted_bytes number;

 13 l_fs1_blocks number;

 14 l_fs1_bytes number;

 15 l_fs2_blocks number;

 16 l_fs2_bytes number;

 17 l_fs3_blocks number;

 18 l_fs3_bytes number;

 19 l_fs4_blocks number;

 20 l_fs4_bytes number;

 21 l_full_blocks number;

 22 l_full_bytes number;

 23 l_free_blks number;

 24 l_total_blocks number;

 25 l_total_bytes number;

 26 l_unused_blocks number;

 27 l_unused_bytes number;

 28 l_LastUsedExtFileId number;

 29 l_LastUsedExtBlockId number;

 30 l_LAST_USED_BLOCK number;

 31 procedure p( p_label invarchar2, p_num innumber)

 32 is

 33 begin

 34 dbms_output.put_line(rpad(p_label,40,'.')||

 35 p_num );

 36 end;

 37 begin

 38 p_segname :=upper(p_segname_1);

 39 p_owner :=upper(p_owner_1);

 40 p_type := p_type_1;

 41 

 42 if(p_type_1 ='INDEX'or p_type_1 ='index')then 

 43 p_type :='INDEX';

 44 endif;

 45 if(p_type_1 ='TABLE'or p_type_1 ='table')then 

 46 p_type :='TABLE';

 47 endif;

 48 if(p_type_1 ='CLUSTER'or p_type_1 ='cluster')then 

 49 p_type :='CLUSTER';

 50 endif;

 51 

 52 dbms_space.unused_space

 53 ( segment_owner => p_owner,

 54 segment_name => p_segname,

 55 segment_type => p_type,

 56 total_blocks => l_total_blocks,

 57 total_bytes => l_total_bytes,

 58 unused_blocks => l_unused_blocks,

 59 unused_bytes => l_unused_bytes,

 60 LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId,

 61 LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,

 62 LAST_USED_BLOCK => l_LAST_USED_BLOCK );

 63 

 64 if p_space ='MANUAL'or(p_space <>'auto'and p_space <>'AUTO')then

 65 dbms_space.free_blocks

 66 ( segment_owner => p_owner,

 67 segment_name => p_segname,

 68 segment_type => p_type,

 69 freelist_group_id =>0,

 70 free_blks =>l_free_blks );

 71 

 72 p('Free Blocks', l_free_blks );

 73 endif;

 74 

 75 p('Total Blocks', l_total_blocks );

 76 p('Total Bytes', l_total_bytes );

 77 p('Unused Blocks', l_unused_blocks );

 78 p('Unused Bytes', l_unused_bytes );

 79 p('Last Used Ext FileId', l_LastUsedExtFileId );

 80 p('Last Used Ext BlockId', l_LastUsedExtBlockId );

 81 p('Last Used Block', l_LAST_USED_BLOCK );

 82 

 83 

 84 /*IFthe segment is analyzed */

 85 if p_analyzed ='Y'then

 86 dbms_space.space_usage(segment_owner => p_owner ,

 87 segment_name => p_segname ,

 88 segment_type => p_type ,

 89 unformatted_blocks => l_unformatted_blocks ,

 90 unformatted_bytes => l_unformatted_bytes,

 91 fs1_blocks => l_fs1_blocks,

 92 fs1_bytes =>l_fs1_bytes ,

 93 fs2_blocks => l_fs2_blocks,

 94 fs2_bytes =>l_fs2_bytes,

 95 fs3_blocks => l_fs3_blocks ,

 96 fs3_bytes =>l_fs3_bytes,

 97 fs4_blocks => l_fs4_blocks,

 98 fs4_bytes =>l_fs4_bytes,

 99 full_blocks => l_full_blocks,

100 full_bytes => l_full_bytes);

101 dbms_output.put_line(rpad(' ',50,'*'));

102 dbms_output.put_line('Thesegment is analyzed');

103 p('0% -- 25% free space blocks', l_fs1_blocks);

104 p('0% -- 25% free space bytes', l_fs1_bytes);

105 p('25% -- 50% free space blocks', l_fs2_blocks);

106 p('25% -- 50% free space bytes', l_fs2_bytes);

107 p('50% -- 75% free space blocks', l_fs3_blocks);

108 p('50% -- 75% free space bytes', l_fs3_bytes);

109 p('75% -- 100% free space blocks', l_fs4_blocks);

110 p('75% -- 100% free space bytes', l_fs4_bytes);

111 p('Unused Blocks', l_unformatted_blocks );

112 p('Unused Bytes', l_unformatted_bytes );

113 p('Total Blocks', l_full_blocks);

114 p('Total bytes', l_full_bytes);

115 endif;

116 end;

117 /

 

 

SQL>EXEC SHOW_SPACE('TEST_TAB','CHENLONG');

Free Blocks.............................15384

Total Blocks............................16384

Total Bytes.............................134217728

Unused Blocks...........................999

Unused Bytes............................8183808

Last Used Ext FileId....................12

Last Used Ext BlockId...................15369

Last Used Block.........................25

 

PL/SQLprocedure successfully completed.

 

Elapsed:00:00:00.14


这里共有 16384 个块,空余 15383 块,其中没有使用的块的有 999 个块,LAST USED BLOCK 表示在最后一个使用的 EXTENT 中使用的 BLOCK.


这里有一个计算 HWM 位置的公式:

探究 Oracle 高水位对数据库性能影响

根据这个公式那么 HWM 位置:


探究 Oracle 高水位对数据库性能影响


那么这个就是 HWM 所有的 BLOCK 编号。

HWM 所在的块:


探究 Oracle 高水位对数据库性能影响

也就是说,HWM 在第 15385 个块,其 BLOCKID 是15343.


探究 Oracle 高水位对数据库性能影响

在使用 ALTER TABLE TEST_TAB DEALLOCATE UNUSED 后,UnusedBlocks 变成了7个,其余的和之前的没什么变化。


探究 Oracle 高水位对数据库性能影响

在执行 ALTERTABLE TEST_TAB MOVE 后,有了很大的变化。

那么 HWM 位置 :


探究 Oracle 高水位对数据库性能影响

那么这个就是 HWM 所有的 BLOCK 编号。

HWM 所在的块:


探究 Oracle 高水位对数据库性能影响

这里比较奇怪的时,没有数据,但是 Unused Blocks 是7,

 

查询查询该表,


探究 Oracle 高水位对数据库性能影响


执行时间就变成了1毫秒,逻辑读变成了3,物理读变成了0个。

 

现在,插入一些数据,


探究 Oracle 高水位对数据库性能影响

分析表的统计信息,


探究 Oracle 高水位对数据库性能影响

从统计信息来看当前块变成了1,总行数为1行。


探究 Oracle 高水位对数据库性能影响
从中我们也可以发现,分析表和 SHOW_SPACE 显示的数据有点不一致,其实这两个都是准的,只不过计算的方法有点不同。


现在,再来试试其他方法,在测试前还是插入数据。


探究 Oracle 高水位对数据库性能影响

分析表的统计信息,


探究 Oracle 高水位对数据库性能影响

TRUNCATE 后,块数变成了0,行数变成0.

实际上除了 MOVE 操作还有 SHRINK SPACE,都能够是高水位线重置。

 

最后,再来看看在创建表时,会默认分配多少个块。


探究 Oracle 高水位对数据库性能影响

INITIAL 等于 65536,即等于 64kb,一个标准块是 8K,正好是8个 block。

PCTFREE 代表着设定为 10 ,意思就是说,当 BLOCK 使用到达 90% 的时候,就不可以在使用了,这个 BLOCK 应该从 FREELIST 列表中移除 (un-link) .


探究 Oracle 高水位对数据库性能影响

以上是 MSSM 管理下 HWM 的分析,在分析中数据不是很直观的看出 HWM 的移动,下面再举一个 ASSM 管理下的 HWM 移动例子:


探究 Oracle 高水位对数据库性能影响

插入数据:


探究 Oracle 高水位对数据库性能影响

然后对该数据文件段头进行 dump 分析:


探究 Oracle 高水位对数据库性能影响


可以看到此时的 LHWM 的 block 位置是在 0x01c00080,同 HHWM 位置,

truncate 该表: 


SQL>truncatetable test_hwm;

Table truncated.


重新 dump 文件.


探究 Oracle 高水位对数据库性能影响

此时 HHWM 和 LHWM 的 block 位置并没有发生改变。

 

再插入更多行。


探究 Oracle 高水位对数据库性能影响

在重新插入了数据后,HHWM 与 LHWM 位置发生了改变,HHWM 往前推移。

 

下面测试下利用 append 方法插入数据会怎么样:


探究 Oracle 高水位对数据库性能影响

查看 dump 文件:


探究 Oracle 高水位对数据库性能影响

可以看出 LHWM 位置并没有发生改变,而 HHWM 往前推移了。以 append 方式批量插入的记录,其存储位置在 hwm 之上,即使 hwm 之下存在空闲块也不能使用。


用 insert /*+append*/ 后,数据的 undo 和 redo 没有生成。因为 HWM 在移动的过程中,这些 block 是不能被其他 process 使用的,那么意味着,只要记录下该次 direct insert 所涉及到的空间的 redo 和 undo  ,在失败回滚的时候,只需要把这些空间修改为原来的状态就可以,而不用逐个记录去 delete。


三. HWM 的利弊


在我们的系统中,如果经常对一个存储对象进行删除和更新,就会在它分配的空间内形成一定的零散空间,这些零散的空间将会影响到 SQL 的访问性能。Oracle 数据库通过跟踪段中的状态来管理空间,于是引进了高水位标记(high water mark)。这样可以区别出那些数据块是没有格式化和未使用的,也就是说当请求新的空闲块,并且现有空闲列表中的块不能满足要求时,HWM 指向的块将被标记为已使用,然后 HWM 将移动指向下一个未使用过的块,这样以便于进行数据插入和数据块管理。


然而,频繁的删除并不会使得高水位的“标记”下移,这使得在做全表扫描时,会依然按原来“标记”的位置去尝试查询所有数据(实际上将扫描很多空块),那么访问时间将会被浪费。


四. HWM 的处理


上面讲解了 HWM 的原理和推进过程,如果出现了高水位该怎么办呢?


1Move


所谓 move 操作也就是将一个表的所有数据,在新分配的空间 (extents 中,可以在原表空间,也可以在新的表空间)中插入,当单个 extents 不够时,继续分配更多的 extents 放入数据,知道将所有的数据放入后,在最后的数据所在的块后标志 HWM。从上面的描述可以看出,move 相当于创建新的段,把数据插入,然后将原来的空间释放,而新段的 HWM自然就随着新插入数据后移,这个新建的段就是一个重置 HWM 后的紧凑表。


在使用 move 操作中,有几个注意事项:


  • Rebuild index

    在对表进行 move 操作后,表中的 rowid 发生了改变,这样导致索引无法定位到原来表中的数据,从而触发了索引失效,所以需要 alter index index_name rebuild【online】的命令进行重建。

  • 空间分配

    Alter  table move 操作,不管你有没有插入数据,它都会占用一些块,这就像我们在移动文件,很明显,移动的过程中是会占用双倍的空间,因此 ORACLE 必须给它分配必要的空间,这时可能会出现 ORA-01652 告警。

  • exclusive lock

    move 操作相当于将表中所有数据移动,因此在 move 的过程中,oracle 会对表放置了 exclusive lock 锁,此时只能对它进行 select 操作。


当然,move 也有一些其他的好处,例如:


  • move 不但可以重置 HWM,解决松散表带来的 IO 浪费,还可以解决表中的行迁移问题;

  • move 可以将表移动到其他表空间,也可以在原表空移动,这样可以一定程度解决表空间碎片;

  • 如果表空间上有大量表、索引被 drop(或者 truncate),导致表空间前半部分出现大量空闲空间,可以通过 move 将靠后的表移动到前面的空闲空间,从而收缩数据文件。

 

下面的脚本,可以找出当前数据库中数据文件可以收缩到的最小大小:


SQL>set linesize 200                      

SQL>columnfile_nameformat a50 word_wrapped

SQL>column smallest format999,990 heading "Smallest|Size|Poss

string beginning""Smallest|..." missing terminating quote (").

SQL> column currsizeformat 999,990 heading "Current|Size"

SQL> column savings  format 999,990 heading "Poss.|Savings"

SQL> select file_name,

  2        ceil( (nvl(hwm,1)*&&blksize)/1024/1024 ) smallest,

  3        ceil( blocks*&&blksize/1024/1024) currsize,

  4        ceil( blocks*&&blksize/1024/1024) -

  5        ceil( (nvl(hwm,1)*&&blksize)/1024/1024 ) savings

  6  fromdba_data_files a,

  7      ( select file_id, max(block_id+blocks-1) hwm

  8          from dba_extents

  9         group by file_id ) b

 10 where a.file_id = b.file_id(+)

 11  /

Enter value for blksize:8192

old   2:       ceil( (nvl(hwm,1)*&&blksize)/1024/1024 ) smallest,

new   2:       ceil( (nvl(hwm,1)*8192)/1024/1024 ) smallest,

old   3:       ceil( blocks*&&blksize/1024/1024) currsize,

new   3:       ceil( blocks*8192/1024/1024) currsize,

old   4:       ceil( blocks*&&blksize/1024/1024) -

new   4:       ceil( blocks*8192/1024/1024) -

old   5:       ceil( (nvl(hwm,1)*&&blksize)/1024/1024 ) savings

new   5:       ceil( (nvl(hwm,1)*8192)/1024/1024 ) savings

 

                                                               Current    Poss.

FILE_NAME                                           SMALLEST     Size  Savings

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

+DATA/prod/datafile/system.256.903827475                 1205    1,210       5

+DATA/prod/datafile/undotbs2.268.903828289                 25       25       0

+DATA/prod/datafile/sysaux.257.903827475                  593      630      37

+DATA/prod/datafile/users.259.903827477                    67      172     105

+DATA/prod/datafile/example.267.903827687                 313      346      33

+DATA/prod/datafile/undotbs1.258.903827477                763      930     167

+DATA/prod/datafile/user_data                               9       50      41

 

7 rows selected.

 

SQL> select 'alterdatabase datafile ''' || file_name || ''' resize ' ||

  2        ceil( (nvl(hwm,1)*&&blksize)/1024/1024 )  || 'm;' cmd

  3  fromdba_data_files a,

  4      ( select file_id, max(block_id+blocks-1) hwm

  5          from dba_extents

  6         group by file_id ) b

  7 where a.file_id = b.file_id(+)

  8   and ceil( blocks*&&blksize/1024/1024) -

  9       ceil( (nvl(hwm,1)*&&blksize)/1024/1024 ) > 0

 10  /

old   2:       ceil( (nvl(hwm,1)*&&blksize)/1024/1024 )  || 'm;' cmd

new   2:       ceil( (nvl(hwm,1)*8192)/1024/1024 ) || 'm;' cmd

old   8:  and ceil( blocks*&&blksize/1024/1024) -

new   8:  and ceil( blocks*8192/1024/1024) -

old   9:      ceil( (nvl(hwm,1)*&&blksize)/1024/1024 ) > 0

new   9:      ceil( (nvl(hwm,1)*8192)/1024/1024 ) > 0

 

CMD

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

alter database datafile'+DATA/prod/datafile/system.256.903827475' resize 1205m;

alter database datafile'+DATA/prod/datafile/sysaux.257.903827475' resize 594m;

alter database datafile'+DATA/prod/datafile/users.259.903827477' resize 67m;

alter database datafile'+DATA/prod/datafile/example.267.903827687' resize 313m;

alter database datafile'+DATA/prod/datafile/undotbs1.258.903827477' resize 763m;

alter database datafile'+DATA/prod/datafile/user_data' resize 9m;

2shrink


此命令为 Oracle 10g 新增功能,shrink 操作是将原本松散的数据存放结构,通过将表中靠后的行向前面的空闲块迁移,在完成后将完全空闲的区释放,并前置 HWM 到表中最后一个使用块的位置,从而实现松散表重新结构紧凑。注意在执行该指令之前必须启动行移动特性:alter table table_name enable row movement。同时该命令只支持 ASSM 管理的表空间,否则会报ORA-10635: Invalid segment or tablespace type 告警。

3Emp/Imp 或数据泵


使用导入导出的方法也可以达到降低 HWM 的目的,其原理上还是属于重建表的过程。


4DBMS_REDEFINITION


利用在线重定义方法,来对表进行重组,从而移动表的数据。

这个操作要求 table 上有一个主键,并要求预先创建一个带有要求修改的存储参数的 table,以便保存重新组织后的数据。具体的操作过程这里不再过多介绍。


案例分析:

上文讲到了高水位推进的情况,下面分享一个执行大量执行 insert 操作,引起的 enq: HW - contention 等待事件.


探究 Oracle 高水位对数据库性能影响

探究 Oracle 高水位对数据库性能影响

探究 Oracle 高水位对数据库性能影响


从这篇 AWR 报告可知,在过去的2小时里,出现 enq: HW -Contention 等待事件,占用 57%的 DB Time。


一般导致 enq: HW -Contention 等待事件的原因,是由于高水位的推进或者格式化数据块而引起。


如果某条会话要插入一条记录,但是表中数据块已经被格式化了,没有多余的空闲空间容纳下这条记录,这时候 Oracle 会重新格式化另一组数据块。在数据插入前,如果想要移动 HWM 的进程必须要获得 HW 锁,为防止多个进程同时修改 HWM。如果此时产生了争用,则会出现 enq: HW - contention 等待。

 

我们可以通过 enq: HW -Contention 等待的 event id,来分析该等待事件。


探究 Oracle 高水位对数据库性能影响

利用 eventid 1645217925,来查看过去会话信息.


探究 Oracle 高水位对数据库性能影响

利用 dbms_utility 包来收集文件号,和所属的块号.


探究 Oracle 高水位对数据库性能影响
查看段所属的用户.


探究 Oracle 高水位对数据库性能影响

到这里基本上可以知道 lob 对象上发生了高水位争用,当然也与主机的存储有关,若存储读写较慢,也会产生争用。这里的解决方法可以参考 MOS 文档 [ID 7319120.8]。

 

上面从原理、实验、案例相结合学习了 HWM 的知识,现在来总结一下。


五. HWM 总结


1. HWM 在插入数据时,当现有空间不足而进行空间的扩展时会向上移,但删除数据时不会往下移,这就好比是水库的水位,当涨水时,水位往上移,当水退出后,留下的水位痕迹还能清晰可见。

 

2. HWM 的信息存储在段头当中。HWM 本身的信息是储存在段头的,在段空间是手工管理方式时(MSSM),ORACLE 是通过 FREELIST(一个单向链表)来管理段内的空间分配,此时可以利用_bump_highwater_mark_count 隐藏参数调整,_bump_highwater_mark_count 隐藏参数指出了单次高水位上涨的块数,默认值是5。如果表的数据增长快,或者经常看到与 HWM 相关的 enq:HW –Contention 等待,可以考虑设置较大的值。但需要注意的是,该隐含参数将影响整个 DB,过大的设置会带来全表扫描性能的进一步恶化以及空间的浪费,因此设置应谨慎。在段空间是自动管理方式时 (ASSM),ORACLE 是通过 BITMAP 来管理段内的空间分配.

 

3. ORACLE 的全表扫描是读取高水位标记(HWM)以下的所有块。当用户发出一个全表扫描时,Oracle 访问目标表里的数据,会从该表所占用的第一个区(Extent)的第一个块(Block)开始扫描,一直扫描到该表的高水位线(HWM),即使它什么也没有发现。这样不仅延长了全表扫描的时间,而且影响全表扫描的性能。比如在一个空表执行 count (*)操作,也会花较长的时间才返回0行数据。

 

4. 在 delete 删除大量数据时,不仅删除时间较长,而且 HWM 保持原位置不动。如果全表的数据确实不再需要,建议使用 truncate 来代替 delete 操作,因为truncate 默认下会对空间进行释放,改变了表中的数据块位置,使得 HWM 重置到段头。其次,truncate 由于不产生回滚,所以在相同的数据量删除的情况下,truncate 会比 delete 快。(注:truncate 不提交回滚,删除数据后可能无法恢复,在删除时要注意)


如何加入云和恩墨大讲堂微信群



云和恩墨
数据驱动,成就未来。整合业界顶尖的技术与合作伙伴资源,围绕数据及相关领域,提供解决方案和专业服务。
IT基础架构
zData一体机 - 分布式存储解决方案
数据架构
Oracle DB2 mysql NoSQL
专项服务: 架构 / 安全 / 高可用 / 容灾 / 优化 / SQL 质量管控
运维服务:运维服务  | 代维服务
人才培养:个人认证 | 企业内训
软件产品:SQL审核 - Z3 | 监控 - Zone | 数据恢复 - ODU
应用架构

应用软件开发:数据建模 SQL审核和优化 | 中间件服务

业务架构

电子渠道(网络销售)分析系统 | 数据治理

恩墨学院

恩墨学院是云和恩墨(北京)信息技术有限公司旗下的培训事业部,创业数年专注于数据库认证、技能培训,以专业的讲师塑造品牌,以专业的训练保证就业,目前已经发展成为国内数据库领域培训领导品牌。


以上是关于探究 Oracle 高水位对数据库性能影响的主要内容,如果未能解决你的问题,请参考以下文章

Oracle高水位线(HWM)及性能优化

oracle数据库,怎么降低高水位线

什么是Oracle高水位线

Oracle 高水位说明和释放表空间,加快表的查询速度

oracle 高水位线

Oracle高水位线 HWM降低技巧