以下是小编帮大家整理的浅谈Oracle的高水位线HWM,本文共8篇,供大家参考借鉴,希望可以帮助到您。

篇1:浅谈Oracle的高水位线HWM

浅谈Oracle的高水位线--HWM

高水位是记录段里能容纳数据的上限,高水位存在段里

全表扫先读段头块,而后在段头块里面找到HWM

下面用实验由内而外来理解Oracle的HWM

[sql]

--t表有一条数据

hr@ORCL>select * from t;

ID NAME

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

1 AAAAA

--找t段的段头块

hr@ORCL>select header_file,header_block from dba_segments where segment_name='T' and wner='HR';

HEADER_FILE HEADER_BLOCK

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

4     387

--另开一个session,dump段头块

sys@ORCL>alter session set tracefile_identifier='sys_dump_t_01';

Session altered.

sys@ORCL>alter system dump datafile 4 block 387;

System altered.

dump的部分trc内容摘入

[sql]

Extent Control Header

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

Extent Header:: spare1: 0   spare2: 0   #extents: 1   #blocks: 8

last map 0x00000000 #maps: 0   offset: 2716

Highwater:: 0x01000189 ext#: 0   blk#: 8   ext size: 8 --Highwater就是高水位,

0x01000189这个是HWM的地址

#blocks in seg. hdr's freelists: 0

#blocks below: 5

mapblk 0x00000000 offset: 0

Unlocked

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

Low HighWater Mark :

Highwater:: 0x01000189 ext#: 0   blk#: 8   ext size: 8

#blocks in seg. hdr's freelists: 0

#blocks below: 5

mapblk 0x00000000 offset: 0

Level 1 BMB for High HWM block: 0x01000181

Level 1 BMB for Low HWM block: 0x01000181

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

Segment Type: 1 nl2: 1   blksz: 8192 fbsz: 0

L2 Array start offset: 0x00001434

First Level 3 BMB: 0x00000000

L2 Hint for inserts: 0x01000182

Last Level 1 BMB: 0x01000181

Last Level II BMB: 0x01000182

Last Level III BMB: 0x00000000

Map Header:: next 0x00000000 #extents: 1  obj#: 52713 flag: 0x10000000

Inc # 0

Extent Map

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

0x01000181 length: 8

Auxillary Map

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

Extent 0  : L1 dba: 0x01000181 Data dba: 0x01000184

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

Second Level Bitmap block DBAs

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

DBA 1: 0x01000182

d dump data blocks tsn: 4 file#: 4 minblk 387 maxblk 387

[sql]

--对t表做一次全表扫

hr@ORCL>set autot traceonly

hr@ORCL>select * from t;

Execution Plan

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

Plan hash value: 1601196873

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

| Id | Operation    | Name | Rows | Bytes | Cost (%CPU)| Time  |

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

| 0 | SELECT STATEMENT |   |  1 |  20 |  3 (0)| 00:00:01 |

| 1 | TABLE ACCESS FULL| T  |  1 |  20 |  3 (0)| 00:00:01 |

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

Note

-----

- dynamic sampling used for this statement

Statistics

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

0 recursive calls

0 db block gets

7 consistent gets --全表扫读了6个块

0 physical reads

0 redo size

469 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

这6个块是如何算出来的呢?

[sql]

hr@ORCL>select file_id,block_id,blocks from dba_extents where segment_name='T';

FILE_ID BLOCK_ID  BLOCKS

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

4    385     8

这t段一共用了8个块,分别是385 386 387 388 389 390 391 392 393

Highwater:: 0x01000189 即:4号文件的393号块

这个可由下面dbms_utility包算出

[sql]

sys@ORCL>select to_number('01000189','xxxxxxxx') from dual;

TO_NUMBER('01000189','XXXXXXXX')

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

16777609

sys@ORCL>select dbms_utility.data_block_address_file(16777609) from dual;

DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(16777609)

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

4

sys@ORCL>select dbms_utility.data_block_address_block(16777609) from dual;

DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(16777609)

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

393

读了一次段头块:4号文件387号块

读了高水位之下的388 389 390 391 392 等5个块

这样一共就读了6个块

注:

385是FIRST LEVEL BITMAP BLOCK

386是SECOND LEVEL BITMAP BLOCK

接着分析我们所dump的内容:

[sql]

Low HighWater Mark :

Highwater:: 0x01000189 ext#: 0   blk#: 8   ext size: 8

接下来谈谈highwater mark 和 low highwater mark

low high water mark与high water mark 之间可能存在formated block也可以可能存在

unformatted block

先来理清dba_tables里面的字段blocks的含义

dba_tables.blocks记录的是分析得到的 formatted block 的总数

而 low hwm 和 high hwm之间可能同时存在 formatted block 和 unfomatted block

所以准确地说 blocks 不能代表 low hwm 或high hwm

如果 low hwm 和 high hwm之间正好没有formatted block时,dba_tables.blocks和

low hwm下的blocks一致

那么什么是Oracle中未格式化的块呢?

未格式化,意思就是这个块,已经是属于这个段了,但是还保留着原来的样子没动

格式化就是把块中的数据清除掉,并把块头改为这个对象的

MSSM表空间中的段,只有一个高水位,高水位下的块都是格式化了的

但是ASSM表空间中的段,有两个高水位:低高水位和高高水位

即上文trc里的:Highwater:: 0x01000189和Low HighWater Mark Highwater:: 0x01000189

低高水位下的块全部是格式化了的

但是低高水位和高高水位之间的块,则可能是格式化了的,也可能是没有

现在的t的高高水位是file 4,block 393;其低高水位是file 4,block 393

我们现在再来看一下t现在data_object_id是多少:

[sql]

hr@ORCL>select object_id,data_object_id from dba_objects where object_name='T';

OBJECT_ID DATA_OBJECT_ID

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

52713     52714

这里很明显t的data_object_id大于object_id

也就是说,在t上曾经发生过move或truncate操作

注意,对于truncate操作而言,truncate后其data_object_id不一定就是在原先的data_

object_id上加1

[sql]

sys@ORCL>select to_char('52714','XXXXXXXX') from dual;

TO_CHAR('

---------

CDEA

换句话说,t中现在在其低高水位和其高高水位之间的block,只要这个block上记录的data

_object_id不等于CDEA

我们可以通过dump里面的Block header dump部分中的seg/obj来判断其data_object_id

是否与段编号相等

那么这个block 就是一个未格式化的块

也就是说,可以通过data_object_id来确定块是在HWM和LHWM的位置

那么Oracle为什么要增加低高水位设置?出于什么目的?全表扫描时,是到低高水位,

还是到高高水位?

Oracle设计有一个原则,就是把一个大操作分散到很多小操作中,以保证某个大操作不会

花费太长时间

无论是延迟提交,还是什么,都体现了这种思想,这和Linux的理念有异曲同工之妙哦

而低高水位线与高高水位线结合,正是这种思想的体现

可以不用一次性格式化所有新分配的块,留一部分给下次操作来完成

全表扫描时,通常都是读至低高水位线,然后根据位图去读低高与高高之间格式化过的块,

避开未格式化的块

如何查看HWM?如何知道HWM下有多少空闲的空间?

最实用的方法就是dump segment_header,速度快,而且对应用没有影响

而且,trc里面的“#blocks in seg. hdr's freelists:”可以告诉我们HWM下有多少空闲块

这里需要注意,如果dba_segments.freelist_groups >1,那么freelist不再segment header中

比如,freelist_group = 3 ,则你便要分别dump header后面的3个块,来看每个group

的freelist的个数

那么如何降低HWM呢?

① expdp/impdp

② 10G及以后的版本可以采用shrink,需要注意的是,表所在表空间须为自动段空间管理

alter table tab_name enable row movement;

alter table tab_name shrink space;

③ 使用move,不过在Move期间,会影响到DML语句,如UPDATE,也需要考虑空间问题

总之move会锁表 而且是TM 另外还会影响index,所以,之后记得rebuild index

alter table move tab_name; 在当前表空间中move

alter table move tab_name tablespace tbs_name; 将其move到其他表空间

④ CTAS 然后rename,rebuild index

⑤ 在线重定义

等等.......

篇2:Oracle Freelist和HWM原理探讨及相关性能优化数据库教程

oracle|性能|优化

Oracle Freelist和HWM原理探讨及相关性能优化

中兴通讯重庆研究所 游波

关键词:Freelist,HWM,存储参数,段,块,dump,优化

文章摘要:

近期来,FreeList的重要作用逐渐为Oracle DBA所认识,网上也出现一些相关的讨论,本文以FreeList为线索对Oracle的存储管理的原理进行较深入的探讨,涉及Oracle段区块管理的原理,FreeList算法等。而与FreeList密切相关的一个重用特性HWM,与sql性能密切相关,本文也作了原理分析介绍。在原理探讨的基础上,介绍了常用的存储参数分析方法,并对所涉及的存储优化、HWM的优化和Freelist竞争优化作了说明。

缩略语:

ASSM:auto segement space management

HWM:high water mark

DBA:data block address

OLTP:online transaction process

OPS:oracle parallel server

1.简介

Oracle的空间管理和存储参数管理是Oracle管理及优化的重要部分。FreeList作为Oracle底层存储参数中的核心参数,其行为方式对Oracle的存储管理及性能优化有重大影响,而现有的Oracle文档对此方面的内容比较缺乏。虽然Oracle 9i已出现了ASSM,但是作为深入调优对FreeList认识仍是必要的。

近期来,FreeList的重要作用逐渐为Oracle DBA所认识,网上也出现一些相关的讨论。本文以FreeList为线索对Oracle的存储管理的原理进行较深入的探讨,涉及Oracle段区块管理的原理,FreeList算法等。而与FreeList密切相关的一个重用特性HWM,与sql性能密切相关,本文也作了原理分析介绍。在原理探讨的基础上,介绍了常用的存储参数分析方法,并对所涉及的存储优化、HWM的优化和Freelist竞争优化作了说明。

这些原理分析和性能优化都建立在探讨的基础上,限于篇幅和本人经验可能存在局限、偏差或谬误。

为了准确文中部分结构和字段的说明直接用英文描述。

限于篇幅本文不对同样很重要的block结构作更深入的讨论,对OPS性能有重要影响的free list group本文也未提及,因此本文在单一free list group下讨论。对于block的深入讨论、free list group的介绍与优化以及PCTUSED和PCTFREE等重要参数的优化请参见参考文献和资料。

2.原理探讨

FreeList作为一个Oracle存储管理的核心参数。其行为方式由Oralce内部控制,我们一般不需要掌握和控制。但是我们可能会遇到这些问题,当插入一条记录,会插入到那个块中?是使用新块,还是插入有数据的老块?段是什么时候扩展的,如何扩展的?表中只有一条记录,但是作一次select时代价却是上千个块,为什么?如果我们从原理上清楚了Oracle的存储管理方式,对相关这些问题的解决及性能优化就清晰自然了。

2.1 Oracle的逻辑储存结构

Oralce的逻辑存储结构按表空间,段,区,块进行管理。块是Oracle用来管理存储空间的最基本单元,Oracle数据库在进行输入输出操作时,都是以块为单位进行逻辑读写操作的。区由一系列连续的块组成,Oralce在进行空间分配、回收和管理时是以区为基本单位的。段由多个区组成,这些区可以是连续的也可以是不连续的,一般情况下一个对象拥有一个段。表空间中容纳段和区。

在生成段的时候,会同时分配初始区(initial extents), 初始区的第一个块就格式化为segment header,并被用来记录free list描述信息、extents信息,HWM信息等。

2.2 free list概念

free list是一种单向链表用于定位可以接收数据的块,在字典管理方式的表空间中,Oracle使用free list来管理未分配的存储块。Oracle记录了有空闲空间的块用于insert或Update。空闲空间来源于两种方式:1.段中所有超过HWM的块,这些块已经分配给段了,但是还未被使用。2.段中所有在HWM下的且链入了free list的块,可以被重用。free list具有下列属性

l        flag指示free list 被使用(1)或未使用(0)

l        free list 链的首块的地址DBA(data block address)

l        free list 链的尾块的地址DBA

free list 的信息通常保留在segment header中,这里给出segment header block dump片段加以说明:

nfl = 3, nfb = 1 typ = 1 nxf = 0

SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000

SEG LST:: flg: USED  lhd: 0x03c00233 ltl: 0x03c00233

SEG LST:: flg: USED  lhd: 0x03c00234 ltl: 0x03c00234

SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000

Segment Header:

==>nfl: number of free lists/block

==>nfb: number of free list blocks + segment header

==>typ: block type

==>nxf: number of transaction free lists

Segment List:

==>flg: flag USED or UNUSED the free list

==>lhd: head of free list

==>ltl: tail of free list

在每一个块中都有一个标记flg用来表明块是否链入了 free list链中。如果这个标志置上,该块中后向指针指向free list链中下一个块的DBA。如果当前块是链的最末尾的块,该后向指针值为0。

这里给出位于free list上的block dump的片段

Block header dump: 0x03c00235

Object id on Block? Y

seg/obj: 0xe2d8 csc: 0x00.6264c61 itc: 1 flg: O typ: 1 - DATA

fsl: 1 fnx: 0x3c00234 ver: 0x01

==>Seg/obj Object ID in dictionary

==>csc SCN of last block cleanout

==>itc Number of ITL slots

==>flg O = On freelist , - = Not on freelist

==>typ 1 = DATA  2 = INDEX

==>fsl ITL TX freelist slot

==>fnx DBA of NEXT block on freelist

举例来说如果有五个块在free list中,分别为A,B,C,D,E

就会形成segment header->A->B->C->D->E--|

同时segment header->E

2.3 free list类别

在段中存在3类free list, 即Master Freelists (MFL), Process Freelists (PrFL), 和 Transaction Freelists.

2.3.1 Master Free List(公用空闲空间池):

每一个段中有一个Master free list,在段创建的时候自动生成。对于每一个段来说都有这样一个空闲空间池,对每个进程都是公用的,空闲空间就是位于master free list 的块上。由于Master free list是公用的,因此当多个进程同时插入行到同一个段上,master free list竞争使用程度就会增加。

2.3.2 Process Free Lists

为了减少Master Free list的竞争问题, 引入了另一种free list叫做Process free lists, 根据sql命令 CREATE/ALTER 中的参数FREELISTS 创建. 这样多个free list 就可以分摊空闲空间的管理,以提高OLTP应用作高度并发插入和更新事务时空间分配管理的性能。通过指定CREATE TABLE / CLUSTER or INDEX的子句STORAGE的参数FREELISTS 来创建,例如: CREATE TABLE flg ( . . . .) . . . STORAGE ( ... FREELISTS 10 ...)。缺省的FREELISTS为1,此时不会创建Process free lists。当FREELISTS>=2时,创建Process free lists。

进程在使用process free list是根据进程的Oracle PID (Process ID)来选择的,公式如下:

select list entry = (PID % NFL) + 1

NFL : FREELISTS定义的Process free list个数

2.3.3 Transaction Free Lists

当Oracle需要时动态创建。一个Transaction Free List 是一种专门给某一个事务使用的free list. 每个段至少有16个transactions free lists, 并且这个值在需要时会增长,直到达到Segment Header块的大小限制。一个事务只有下面情况下会需要分配一个Tx Free Lists entry: 块中释放空间时(DELETE or UPDATE) 并且还不存在Tx Free Lists entry时。

2.4 Free list行为2.4.1 Freelist Link and Unlink 操作

Freelist 按后进先出队列(LIFO) 方式管理。也就是说最后被link到freelist的块拥有最先unlink的机会。

当块中空闲空间增加到大于PCTFREE时,块放入freelist中。free list中的块可用来作update 或insert。 当块中没有足够的空间用于insert操作时并且使用空间大于PCTUSED,块就会从free list中移出。

在块在DELETE or UPDATE 操作之后,如果使用空间落到PCTUSED下,块再次link到free list中。每次块加入free list时,都是link到链表的头部。

例如:考虑段中有120个块编号由1到120。其中有6个块在free list上并假设HWM是 80。(block实际使用DBA编号)

10->24->45->46->65->80-|

现在作INSERT 操作,需要400 bytes空间。假设块10上空间不足,但块24上空间可用。现在数据插入到块 24 ,现在块24的剩余空间小于该表的PCTUSED。因此块 24 从free list链表中移出。PCTFREE and PCTUSED参数的目的就是用来控制数据块从free list的链表中移入/移出行为的。现在free lists象这样:

10->45->46->65->80-|

然后在同一事务中作DELETE同一个段的数据,使块 54 和 67落到PCTUSED下。现在这些块加入到free list链中。free list链现在象这样:

67->54->10->45->46->65->80-|

2.4.2 Transaction Free List 算法

扫描segment Header块中所有的Tx free list,检查是否还没有Tx free list entry分配给transaction, 如何没有,将寻找未使用的entry或已经提交了事务的空的Tx free list。如果上述搜索过程失败, 新的entry会在segment Header块中Tx free lists区域中开辟。如果没有空间来生成, 事务就必须等待entry的释放。

segment header中的最大free list个数:

Block Size   Max # Freelists

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

2K    24

4K    50

8K    101

16k    204

事务T1释放出来的空闲块(DELETE or UPDATE)的使用 :

l        立即被T1所重用

l        当T1 commit后被其它需要空闲块的事务重用,过程举例如下:

2.5 HMW概念

HIGH WATER MARK代表一个表使用的最大的(top limit)块 。2.1中已经提到HIGH WATER MARK 记录在segment header中,并且在Oracle插入数据时一般增长5个blocks(并非总是5个块,具体参见2.4.2中流程图中HMW增长方式)。

segment header block中与HWM相关信息说明如下:

EXTENT CONTROL:

Extent Header:: spare1: 0     space2: 0     #extents: 13    #blocks: 1429

last map 0x00000000 #maps: 0     offset: 4128

Highwater:: 0x04d0 ext#: 12    blk#: 275   ext size: 475

#blocks in seg. hdr's freelists: 5

#blocks below: 1229

mapblk 0x00000000 offset: 12

Unlocked

==>spare1:  this field is no longer used (old inc#, now always 0)

==>space2:  this field is no longer used (old ts#, now always 0)

==>#extents: number of extents allocated to segment

==>#blocks: number of blocks allocated to segment

==>last map: address of last extent map block

0 if extent map is entirely in the segment header

==>#maps:   number of extent map block

==>offset:  offset to end of extent map

==>HWM dba: address of block at highwater mark

==>ext#:    HWM extent number relative to segment

==>blk#:    HWM block number within extent

==>ext size: HWM extent size (in blocks)

==>#blocks in seg. hdr's freelists: number of blocks in seg. hdr's free list

==>#blocks below: number of blocks below HWM

==>mapblk dba: dba of extent map block containing HWM extent

is 0 if HWM is in the segment header

==>offset:  offset within extent map block

is the ext# if HWM is in segment header

==>Locked by: if locked by a transaction, the xid is displayed

HWM可以说是已经使用过的存储空间和未使用过的存储空间之间的分界线。在表使用过程中,HWM一直向一个方向移动,插入记录时HWM可能会向增加的方向移动,但是删除记录时HWM并不会向相反的方向移动。参见2.4.2。下图显示了某个数据段中HWM的位置情况。

图2.5

HIGH WATER MARK之所以重要是因为它对全表扫描性能的影响,

当实施一个全表扫描时,Oracle会读取所有HIGH WATER MARK下的块即使它们是空块。当HIGH WATER MARK 下有很多unused block时实施全表扫描会增加额外的不必要的I/O。它也会在全局共享区中填充很多很多空块。

3.分析方法

存储参数基本上属于oracle internal的东西,因此oralce并没有提供很好的手段来分析。但是对于DBA来说,还是可以通过block dump和DBMS_SPACE等手段来获取部分信息。

3.1 提取block和free list信息

创建dbms_space使用的存储过程show_space

SQL>

create or replace procedure show_space

( p_segname in varchar2,

p_owner in varchar2 default user,

p_type in varchar2 default 'TABLE',

p_partition in varchar2 default NULL )

as

l_free_blks number;

l_total_blocks number;

l_total_bytes number;

l_unused_blocks number;

l_unused_bytes number;

l_LastUsedExtFileId number;

l_LastUsedExtBlockId number;

l_last_used_block number;

procedure p( p_label in varchar2, p_num in number )

is

begin

dbms_output.put_line( rpad(p_label,40,'.') || p_num );

end;

begin

dbms_space.free_blocks

( segment_owner =>p_owner,

segment_name =>p_segname,

segment_type =>p_type,

partition_name =>p_partition,

freelist_group_id =>0,

free_blks =>l_free_blks );

dbms_space.unused_space

( segment_owner =>p_owner,

segment_name =>p_segname,

segment_type =>p_type,

partition_name =>p_partition,

total_blocks =>l_total_blocks,

total_bytes =>l_total_bytes,

unused_blocks =>l_unused_blocks,

unused_bytes =>l_unused_bytes,

last_used_extent_file_id =>l_LastUsedExtFileId,

last_used_extent_block_id =>l_LastUsedExtBlockId,

last_used_block =>l_last_used_block );

p( 'Free Blocks', l_free_blks );

p( 'Total Blocks', l_total_blocks );

p( 'Total Bytes', l_total_bytes );

p( 'Unused Blocks', l_unused_blocks );

p( 'Unused Bytes', l_unused_bytes );

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

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

p( 'Last Used Block', l_last_used_block );

end;

过程已创建。

SQL>create table t1(a char(1000)) storage( freelists 3);

表已创建。

SQL>set serveroutput on;

SQL>exec show_space('T1');

Free Blocks.............................0      <==Number of blocks on freelist

Total Blocks............................5      <==Total data blocks in segment

Total Bytes.............................20480  <==Total bytes in segment

Unused Blocks...........................4      <==Total unused blocks in segment

Unused Bytes............................16384  <==Total unused bytes in segment

Last Used Ext FileId....................15     <==File id of last used extent

Last Used Ext BlockId...................562    <==Block id of last used extent

Last Used Block.........................1      <==Last used block in extent

PL/SQL 过程已成功完成。

有关show_space的进一步使用技巧可参考文献5。以下利用上面得到的数据对segment header block进行dump。

SQL>alter system dump datafile 15 block 562;

在udump/ora10792.trc中

*** -09-08 15:29:57.343

Start dump data blocks tsn: 27 file#: 15 minblk 562 maxblk 562

buffer tsn: 27 rdba: 0x03c00232 (15/562)

scn: 0x0000.064560e4 seq: 0x02 flg: 0x00 tail: 0x60e41002

frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED

Extent Control Header

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

Extent Header:: spare1: 0     space2: 0     #extents: 1     #blocks: 4

last map 0x00000000 #maps: 0     offset: 2080

Highwater:: 0x03c00233 ext#: 0     blk#: 0     ext size: 4

#blocks in seg. hdr's freelists: 0

#blocks below: 0

mapblk 0x00000000 offset: 0

Unlocked

Map Header:: next 0x00000000 #extents: 1   obj#: 60033 flag: 0x40000000

Extent Map

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

0x03c00233 length: 4

nfl = 3, nfb = 1 typ = 1 nxf = 0

SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000

SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000

SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000

SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000

End dump data blocks tsn: 27 file#: 15 minblk 562 maxblk 562

对于上述块中字段的说明,以及相关试验。由于篇幅所限,本文不再列举。可参考文献7。

对非segment header的data block的dump方法和上述类似。data block的结构和segment header block不一样,如果需要了解,可查阅参考文献和资料。

3.2 提取HWM信息3.2.1 HWM位置

HWM位置按下面的公式计算:

HWM = useed byte = Total Bytes - Unused Blocks

Total Bytes和Unused Blocks都可以用show_space提取。

还可以通过ANALYZE tables得到HWM信息. DBA_TABLES视图中包含了可用于各表空间分析的列。其中blocks代表已使用过的块即HWM,empty_blocks代表未使用的空间。

3.2.1 HWM下空间利用信息

要比较有数据行的块的块数和HIGH WATER MARK下总块数,可以用下面的公式来展示HWM下未用空间的比例。

p = 1- r/h

r:有数据行的块的块数

h:HWM下的块数.

r可以通过如下方法获得:

Oracle7:

SELECT count(distinct substr(rowid, 15,4) || substr(rowid, 1,8) ) FROM schema.table;

Oracle8 and Oracle9:

SELECT count(distinct substr(rowid, 7,3) || substr(rowid, 10,6) ) FROM schema.table;

如果公式计算的结果 p是0,就不需要对表进行重建。如果结果p大于0,应该考虑系统状况和应用需要来决定是否需要总组表。

4.优化4.1手工回收存储空间

在HIGH WATER MARK以上的块对性能没有影响,但是会耗费空间。如何空间大小是一个考虑的问题,就可以决定回收空块。

假设表T1的存储示意图如图2.5所示,使用ALTER TABLE ... DEALLOCATE UNUSED语句可以回收HWM以上的空间。比如:

alter table t1 deallocate unused;

回收后T1的存储示意如图4.1.1

图4.1.1

如果在ALTER TABLE ... DEALLOCATE UNUSED语句中使用了KEEP关键字,则可以在HWM之后保留指定大小的空闲空间,比如:

alter table t1 deallocate unused keep 10K;

回收后T1的存储示意如图4.1.2

图4.1.2

4.2删减表

根据3.2.1可以得到HWM以下块的使用情况。如何p大于时,对全表扫描性能会产生影响,同时也会耗用空间。

如果能够确认应用有良好的索引几乎不会用到全表扫描,那么HIGH WATER MARK以下的空块,尽管耗费了空间,不会对访问产生影响。如果不能确定,那么就需要考虑删减表。

删减表的操作将删除表中所有的记录,并且重置HWM标记。表在删减之后将成为一个空表。

在Oracle中删减表只有如下的两种办法:

1.使用drop语句

先使用drop语句删除整个表,然后再重建这个表。在删除-重建的过程中,与表相关的所有索引、完整性约束以及触发器都会丢失,并且所有依赖于该表的对象都会变为INVALID状态,同时原来争对表的授权也会失效。因此采用这种方式删除表中的记录代价太大。

2.使用TRUNCATE语句

TRUNCATE语句属于DDL语句,不会产生任何回退信息,并且被立即自动提交。在执行TRUNCATE语句时不会影响到与被删减表相关的任何数据库对象与授权,也不会触发表中所定义的触发器。此外,在对标进行删减时,HWM将重置,已经为表分配的存储空间将被回收。

在执行TRUNCATE语句时,可以通过drop storage子句和reuse storage子句来控制被释放的区是否回收到表空间中。如何作在线系统的TRUNCATE,不希望表长时间锁住,那么可以使用reuse storage子句,仅将HWM重置。

4.3 free list优化

free list 竞争出现在多个进程使用同一个free list并试图同时修改free list头部数据块时。可以通过查询视图v$waitsate的class类型为data block 的记录来检查竞争情况。

产生data block类型竞争的主要原因是多个进程试图同时修改free list头部数据块。 然而,它也会出现在当进程准备将块读入buffer cathe时,另一个进程需要访问同一个块。如果能在V$SESSION_WAIT中正好捕获buffer busy waits,就可以通过查询V$SESSION_WAIT中的P3来判定是那一类。A 0 或 1014代表读类型,其他的值为修改竞争的类型。

下一步需要确定竞争涉及那些段。 如果能够在V$SESSION_WAIT捕获waits,就可以用P1和P2的值 (对应file 和 block) 在DBA_EXTENTS中找到段名。 如何是一个表,就很可能需要重建表来创建更多的process freelists。 一种计算需要创建多少个freelist的方法是dump一些段中接近HWM的块,检查interested transaction list的个数,具体方法可参见3.1。interested transactions个数的峰值加1 就是需要的最小process freelists的值。

从2.3和2.4可以看出,使用多个free list可能导致更多的空块未被使用, 也可能导致段更快地扩展。如果性能是当前所关心的重点,那么多free lists 可以用来提高并发访问能力,当然会增加一些额外空间的耗用。然而,如果空间使用大小是首先考虑的因素,那么推荐使用single freelist,使参数FREELISTS=1, 当然就不能提升并发事务的性能了。

V$WAITSTAT 也可显示其他类型class的竞争,包括segment header 和free list。 出现在同一个free list group中多个事务需要同时更新它们的free list header记录时。 有多种方法来解决这个问题如重建表采用更多的free list groups,或者增加 _bump_highwater_mark_count大小,或者调整应用本身。

参考文献和资料:

1.《FREELISTS and FREELIST GROUPS. SCOPE & APPLICATION 》

2.《INITRANS, MAXTRANS, FREELISTS and FREELIST GROUPS, PCTFREE and PCTUSED》,Mike Ault

3.《Freelist Internals: An OverviewKnowledge》,Xpert for Oracle Administration

4.《Blockdump - 8.x Data Segment Header in Oracle》

5.《AskTom dbms_space_free_space》,asktom.oracle

6.《Data Blocks and Freelists》,www.ixora.au

7.《偷窥Data block 的物理结构》,www.itpub

8.《Oracle 9i for windows nt/2000数据系统培训教程》,清华大学出版社

上述部分文章在我的blog网站blog.csdn/youbo2004上可找到,对于研究free list,free list group和block等有很好的帮助。

篇3:水比杯高

同学们都很惊讶。

丁文涛说:?这个我知道,用的水的表面张力原理。?

马小跳又讲:?我将一个矿泉水瓶底钻孔,装满后不会流出来,你相信吗??

这下可把丁文涛问住了。因为丁文涛未见过。

马小跳找来一只矿泉水瓶,底部钻了几个孔,装满水后竖着拿起,水不流出来。同学们都觉得很奇怪。一会,马小跳将瓶盖轻轻一拧,水就从小孔处流出来了。当把瓶盖拧紧时,水就不流了。大家七嘴八舌地议论起来。

究竟是什么原因?

篇4:高可用性oracle配置步骤Windows系统

硬件环境: 两台HP Server rp5470小型机,7110磁盘阵列 软件环境: HP-UX B.11.11、MirrorDisk/UX B.11.11、MC / Service Guard A.11.14、Oracle 9i for HP-UX, 3.1准备系统 3.1.1编辑 安全 文件: [/@machine01]vi .rhosts文件 machine1 root machine2 roo

硬件环境:

两台HP Server rp5470小型机,7110磁盘阵列

软件环境:

HP-UX B.11.11、MirrorDisk/UX B.11.11、MC / Service Guard A.11.14、Oracle9i for HP-UX。

3.1准备系统

3.1.1编辑安全文件:

[/@machine01]vi .rhosts文件

machine1 root

machine2 root

3.1.2创建根逻辑卷的镜像

[/@machine01]#pvcreate -B /dev/rdsk/c2t2d0

[/@machine01]#vgextend /dev/vg00 /dev/dsk/c2t2d0

[/@machine01]#mkboot -l /dev/rdsk/c2t2d0

[/@machine01]#lvextend -m 1 /dev/vg00/lvol1 /dev/dsk/c2t2d0

[/@machine01]#lvextend -m 1 /dev/vg00/lvol2 /dev/dsk/c2t2d0

[/@machine01]#lvextend -m 1 /dev/vg00/lvol3 /dev/dsk/c2t2d0

[/@machine01]#lvextend -m 1 /dev/vg00/secswap /dev/dsk/c2t2d0

[/@machine01]#lvextend -m 1 /dev/vg00/lvol4 /dev/dsk/c2t2d0

[/@machine01]#lvextend -m 1 /dev/vg00/lvol5 /dev/dsk/c2t2d0

[/@machine01]#lvextend -m 1 /dev/vg00/lvol6 /dev/dsk/c2t2d0

[/@machine01]#lvextend -m 1 /dev/vg00/lvol7 /dev/dsk/c2t2d0

[/@machine01]#lvextend -m 1 /dev/vg00/lvol8 /dev/dsk/c2t2d0

[/@machine01]#/usr/sbin/lvlnboot -b /dev/vg00/lvol1

[/@machine01]#/usr/sbin/lvlnboot -s /dev/vg00/lvol2

[/@machine01]#/usr/sbin/lvlnboot -r /dev/vg00/lvol3

验证镜像是否已正确创建:

[/@machine01]#lvlnboot -v

显示下列信息说明镜像已正确创建

Boot Definitions for Volume Group /dev/vg00:

Physical Volumes belonging in Root Volume Group:

/dev/dsk/c1t2d0 (0/0/1/1.2.0) -- Boot Disk

/dev/dsk/c2t2d0 (0/0/2/0.2.0) -- Boot Disk

Boot: lvol1    on:    /dev/dsk/c1t2d0

/dev/dsk/c2t2d0

Root: lvol3    on:    /dev/dsk/c1t2d0

/dev/dsk/c2t2d0

Swap: lvol2    on:    /dev/dsk/c1t2d0

/dev/dsk/c2t2d0

Dump: lvol2    on:    /dev/dsk/c1t2d0, 0

在machine02机上重复以上步骤

3.1.3创建群集锁卷组和物理卷:

[/@machine01]#pvcreate -f /dev/rdsk/c4t0d0

[/@machine01]#mkdir /dev/vglock

[/@machine01]#mknod /dev/vglock/group C 64 0x00

[/@machine01]#vgcreate /dev/vglock /dev/dsk/c4t0d0

[/@machine01]#vgexport -p -s -m /tmp/vglock.map /dev/vglock

[/@machine01]#rcp /tmp/vglock.map machine02:/tmp/.

[/@machine02]#mkdir /dev/vglock

[/@machine02]#mknod /dev/vglock/group c 64 0x020000

[/@machine02]#vgimport -s -m /tmp/vglock.map /dev/vglock

3.2用LVM创建存储基本结构:

3.2.1创建卷组:

#c4t0d1盘来自磁盘阵列,vg01用于存放oracle库ora9的数据

[/@machine01]#pvcreate -f dev/rdsk/c4t0d1

[/@machine01]#mkdir /dev/vg01

[/@machine01]#mknod /dev/vg01/group c 64 0x010000

[/@machine01]#vgcreate /dev/vg01 /dev/dsk/c4t0d1

[/@machine01]#lvcreate -L 10000 /dev/vg01

[/@machine01]#newfs -F vxfs /dev/vg01/data

[/@machine01]#mkdir /data

[/@machine01]#mount /dev/vg01/data /data

[/@machine01]#vgdisplay -v /dev/vg01 #验证卷组是否已正确创建

3.2.2将卷组分发到二号机:

[/@machine01]#umount /data

[/@machine01]#vgchange -a n /dev/vg01

[/@machine01]#vgexport -p -s -m /tmp/vg01.map /dev/vg01

[/@machine01]#rcp /tmp/vg01.map machine02:/tmp/.

[/@machine02]#mkdir /dev/vg01

[/@machine02]#mknod /dev/vg01/group c 64 0x010000

[/@machine02]#vgimport -s -m /tmp/vg01.map /dev/vg01

[/@machine02]#vgchange -a y /dev/vg01

[/@machine02]#mkdir /data

[/@machine02]#mount /dev/vg01/data /data

[/@machine02]#vgdisplay -v /dev/vg01] #验证配置

[/@machine02]#umount /data

[/@machine02]#vgchange -a n /dev/vg01

3.3建库:

3.3.1建库:

假设Oracle99i数据库软件已经安装在系统中,oracle用户及其环境变量等均已设置好:

ORACLE_BASE=/home/oracle/app

ORACLE_HOME=$ORACLE_BASE/product/9.2.0

ORACLE_SID=ora9

ORACLE_TERM=xterm

NLS_LANG=AMERICAN_AMERICA.ZHS16GBK

ORA_NLS33=$ORACLE_HOME/ocommon/nls/admin/data

LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib:$ORACLE_HOME/rdbms/lib

PATH=/bin:/usr/bin:/usr/sbin:/etc:/opt/bin:/usr/clearcase/“ target=”_blank“ >ccs/bin:/usr/local/bin:$ORACLE_H

OME/bin

按如下步骤执行:

[/@machine01]#vgchange -a y vg01

[/@machine01]#mount /dev/vg01/data /data

启动XWindows,打开一个terminal窗口,在terminal窗口中执行下列命令

[/@machine01]#su - oracle

$vi .profile

DISPLAY=x.x.x.x:0.0 #改DISPLAY变量,x.x.x.x为你当前运行xwindows终端的电脑的ip地址

$exit

[/@machine01]#su - oracle

$dbca

在GUI中选Create a database――New Database――全局数据库名:ora9.world,SID:ora9――Dedicated ServerMode――Initialization Parameters,根据实际需要填参数――改变DataBase Storage画面中Controlfile、datafile、Redo Log文件位置均为/data/――Create a database并生成创建代码――最后改sys及system用户的口令――完成

3.3.2将必要的文件拷贝至二号机:

[/home/oracle/app/admin/@machine02]rcp Cr machine01:/home/oracle/app/admin/ora9 .

[/home/oracle/app/admin@machine02]#chown -R oracle:dba ora9

[/home/oracle/app/product/9.2.0/@machine02]rcp-r machine01:/home/oracle/app/product/9.2.0/dbs .

[/home/oracle/app/product/9.2.0/@machine02]chown -R oracle:dba dbs

3.4配置群集:

3.4.1生成摸板并修改

[/@machine01]#cmquerycl -v -c /etc/cmcluster/clconfig.ascii -n machine01 -n machine02

[/@machine01]#vi /etc/cmcluster/clconfig.ascii

CLUSTER_NAME  oracledb

FIRST_CLUSTER_LOCK_VG /dev/vglock

NODE_NAME machine01

NETWORK_INTERFACE lan2

HEARTBEAT_IP 192.168.100.80

NETWORK_INTERFACE lan0

HEARTBEAT_IP 192.1.1.1

FIRST_CLUSTER_LOCK_PV /dev/dsk/c4t0d0

NODE_NAME machine02

NETWORK_INTERFACE lan0

HEARTBEAT_IP 192.1.1.2

NETWORK_INTERFACE lan2

HEARTBEAT_IP 192.168.100.81

FIRST_CLUSTER_LOCK_PV /dev/dsk/c4t0d0

HEARTBEAT_INTERVAL 2000000

NODE_TIMEOUT 6000000

AUTO_START_TIMEOUT 600000000

NETWORK_POLLING_INTERVAL 2000000

MAX_CONFIGURED_PACKAGES 4 #最大包个数,根据实际情况确定,小于等于60

VOLUME_GROUP /dev/vg01

VOLUME_GROUP /dev/vglock

3.4.2验证群集配置:

[/@machine01]#cmcheckconf -k -v -C /etc/clconfig.ascii

3.4.3分发二进制文件:

[/@machine01]#vgchange -a y vglock #必须仅在发出cmapplyconf命令的节点上激活vglock,这样才可初始化锁磁盘

[/@machine01]#cmapplyconf -k -v -C /etc/cmcluster/clconfig.ascii

[/@machine01]#vgchange -a n vglock

3.4.4启动群集并检查群集:

[/@machine01]#cmruncl -v

[/@machine01]#cmviewcl -v

还可通过断开某节点网络、停下某节点等观察群集是否能正常切换,

3.4.5存储卷组和群集锁配置数据:

[/@machine01]#vgcfgbackup vg01

[/@machine01]#vgcfgbackup vglock

3.5配置高可用性oracle包:

3.5.1建立包目录

[/@machine01]#mkdir /etc/cmcluster/pkg_ora

3.5.2创建包配置文件并进行修改

[/@machine01]#cmmakepkg -p /etc/cmcluster/pkg_ora/pkg_ora.conf

[/@machine01]#vi /etc/cmcluster/pkg_ora/pkg_ora.conf

PACKAGE_NAME  pkg_ora

PACKAGE_TYPE   FAILOVER

FAILOVER_POLICY CONFIGURED_NODE

FAILBACK_POLICY MANUAL

NODE_NAME               machine01

NODE_NAME               machine02

AUTO_RUN                YES

LOCAL_LAN_FAILOVER_ALLOWED YES

NODE_FAIL_FAST_ENABLED   NO

RUN_SCRIPT      /etc/cmcluster/pkg_ora/pkg_oratl

RUN_SCRIPT_TIMEOUT   NO_TIMEOUT

HALT_SCRIPT    /etc/cmcluster/pkg_ora/pkg_oratl

HALT_SCRIPT_TIMEOUT   NO_TIMEOUT

SERVICE_NAME    oracle_service

SERVICE_FAIL_FAST_ENABLED  NO

SERVICE_HALT_TIMEOUT   300

SUBNET    192.168.100.0

3.5.3创建包控制文件并进行修改

[/@machine01]#cmmakepkg -v -s /etc/cmcluster/pkg_ora/pkg_oratl

[/@machine01]#vi /etc/cmcluster/pkg_ora/pkg_oratl

VG[0]=”/dev/vg01“

LV[0]=”/dev/vg01/data“; FS[0]=”/data“; FS_MOUNT_OPT[0]=”-o rw“

IP[0]=”192.168.100.82“

SUBNET[0]=”192.168.100.0“

SERVICE_NAME[0]=”oracle_service“

SERVICE_CMD[0]=”/etc/cmcluster/pkg_ora/oracle9i.sh monitor“

SERVICE_RESTART[0]=”"

function customer_defined_run_cmds

{

# ADD customer defined run commands.

: # do nothing instruction, because a function must contain some command.

/etc/cmcluster/pkg_ora/oracle9i.sh start

test_return 51

}

function customer_defined_halt_cmds

{

# ADD customer defined halt commands.

: # do nothing instruction, because a function must contain some command.

/etc/cmcluster/pkg_ora/oracle9i.sh halt

test_return 52

}

3.5.4修改oracle9i脚本

[/@machine01]#vi /etc/cmcluster/pkg_ora/oracle9i.sh

SID_NAME=ora9

ORACLE_HOME=/home/oracle/app/product/9.2.0

LISTENER_NAME=LISTENER

LISTENER_PASS=

MONITOR_INTERVAL=30

PACKAGE_NAME=pkg_ora

其余部分保持原状

3.5.5验证包配置文件

[/etc/cmcluster/pkg_ora@machine01]#cmcheckconf Cv CC /etc/cmcluster/clconfig.ascii -P pkg_ora.conf

3.5.6分发包二进制文件

[/etc/cmcluster/pkg_ora@machine01]#cmapplyconf -v CC /etc/cmcluster/clconfig.ascii -P pkg_ora.conf

3.5.7修改listener.ora文件

[/home/oracle/app/product/9.2.0/@machine01]#vi listener.ora

将下列条目:

(ADDRESS_LIST =

(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.100.80)(PORT = 1521))

192.168.100.80改为包地址192.168.100.82,其余部分不变。

3.5.8将包目录和listener.ora文件拷贝至二号机

[/etc/cmcluster@machine02]#rcp -r machine01:/etc/cmcluster/pkg_ora .

[/home/oracle/app/product/9.2.0work/@machine02]rcp machine01:/oracle/app/product/9.2.0/network/listener.ora .

[/home/oracle/app/product/9.2.0/network/@machine02]chown oracle:dba listener.ora

3.5.9启动包并观察包是否运行正常

[/@machine01]#cmmodpkg -v -e pkg_ora #启动包

[/@machine01]#cmviewcl -v #观察包及群集是否运行正常

还可通过sqlplus及OEM等oracle实用程序验证oracle包是否运行正常。

原文转自:www.ltesting

篇5:Oracle、SQL Server、Access数据库高效果分页技巧

1、SQL Server、Access数据库

这都微软的数据库,都是一家人,基本的操作都是差不多,常采用如下分页语句:

PAGESIZE:每页显示的记录数

CURRENTPAGE:当前页号

数据表的名字是:components

索引主键字是:id

以下是引用片段:

select top PAGESIZE * from components where id not in

(select top (PAGESIZE*(CURRENTPAGE-1))

id from components order by id)order by id

如下列:

以下是引用片段:

select top 10 * from components where id not in

(select top 10*10 id from components order by id)

order by id

从101条记录开始选择,只选择前面的10条记录

2、Oracle数据库

因为Oracle数据库没有Top关键字,所以这里就不能够像微软的数据据那样操作,这里有两种方法:

(1)、一种是利用相反的,

PAGESIZE:每页显示的记录数

CURRENTPAGE:当前页号

数据表的名字是:components

索引主键字是:id

以下是引用片段:

select * from components where id not

in(select id from components where

rownum<=(PAGESIZE*(CURRENTPAGE-1)))

and rownum<=PAGESIZE order by id;

如下例:

以下是引用片段:

select * from components where id not in

(select id from components where rownum<=100)

and rownum<=10 order by id;

从101到记录开始选择,选择前面10条,

(2)、使用minus,即中文的意思就是减去。

以下是引用片段:

select * from components where rownum

<=(PAGESIZE*(CURRENTPAGE-1)) minus

select * from components where rownum

<=(PAGESIZE*(CURRENTPAGE-2));

如例:select * from components where

以下是引用片段:

rownum<=10 minus select * from components

where rownum<=5;.

(3)、一种是利用Oracle的rownum,这个是Oracle查询自动返回的序号,一般不显示,但是可以通过select rownum from [表名]看到,注意,它是从1到当前的记录总数。

以下是引用片段:

select * from (select rownum tid,components.

* from components where rownum<=100) where tid<=10;

篇6:太湖流域汛期河湖等水位线的判读及其应用

太湖流域汛期河湖等水位线的判读及其应用

在中国湖泊-流域数据库的技术支撑下,绘制出太湖流域20世纪内5次(1931,1954,1983,1991,)梅雨洪水期,不同雨情、水情下的`河湖等水位线.以上述系列图幅为基础,解读了水情及水位发展过程,同时初步分析了等水位线在防洪中的应用,以及新出现的太湖流域第三次水势演变等研究结果.

作 者:毛锐 李国砚 刘晓玫 MAO Rui LI Guoyan LIU Xiaomei  作者单位:中国科学院南京地理与湖泊研究所,南京,210008 刊 名:湖泊科学  ISTIC PKU英文刊名:JOURNAL OF LAKE SCIENCES 年,卷(期): 19(4) 分类号:P3 关键词:太湖流域   等水位线   水势演变  

篇7:如果我是水高国庆 500

如果我变成了水,变成了人类生活中必不可少的水,我会为人们做出巨大的贡献,让人们受益无穷。

如果在春天,我将变成春雨,滋润大地,让每一棵树苗喝足了水,让它们茁壮成长,结出又大又甜的果实,让春天真正成为人类的天堂。农民伯伯看在眼里,喜在心里。

如果在夏天,我会变成蒙蒙的细雨,让炎热的人们感受到凉爽的气息,并且遏制沙尘暴,不让蓝色的天空成为浑黄一体,让天空更蓝,草地更绿。

秋天,天气渐渐转冷。秋高气爽,很多小鱼儿会逆流而上,它们中途会遇到很多危险。这时,我将变成一条小河,护送它们到安全的地方,在水中快活的游玩。

冬天,天气变的非常寒冷,我又变成了雪,和风伯伯一起在天空飞舞,我在稻田里为麦子盖上了一层洁白的棉被,让它们有充足的雪水喝。而且我会把这个世界变的粉妆玉彻,成为一个冰雪童话王国。

如果我是水,我一定会完成我所有的心愿,让人类的生活更加美好

篇8:如果我是水高国庆 500

如果我是水,我最大的梦想就是为云南那些受缺水灾害的人们做上一点小小的贡献。我是水我可以为他(她)们解除干渴,滋润他们的土地,让他们的土地再次长满绿油油的粮食的小苗。

如果我是水,我还要在云南地区变成大海,让云南的同胞们都有水喝,不受干渴的折磨。

如果我是水,我要去浇树,因为,在大自然中,没有了树,人们也是生存不下去的。例如:如果没有树,我们就没有写作的纸,如果没有树,我们将去哪里吸氧气呢?如果没有树,谁又来帮我们挡风沙啊!

所以,如果我是水,我就要用我自己去浇树,这样,树便不会被渴死了。

如果我是水,我还要成为墨汁。因为,在我们写作业的时候,要用钢笔。你说,钢笔没有墨汁,可怎么写作业啊。所以,我如果是水,我就要变成墨汁。

如果你是水,你要做什么呢?

更多推荐

浅谈Oracle的高水位线HWM