oracle点知识——HWM(高水位线) 下

1、何时应该降低 HWM

table中包含两种空闲的block,在HWM之上的空闲block 和 在HWM之下的空闲block。

1、在HWM之上的空闲block : 运行analyze table后,在HWM之上的空心啊block会在user_tables 的 empty_blocks中 被统计,这些空闲的blocks实际上是从来没有存储过数据的,可以用以下命令来释放这些空间:

SQL>  alter table table_name  deallocate unused;

下面做一个实验来验证以下:

SQL> create table my_objects3 as select * from all_objects;

表已创建。            ——创建一个新表,一会用于测试

先分析一下:

SQL> exec show_space(p_segname=>'MY_OBJECTS3' ,p_owner=> 'SYS' ,p_type=>'TABLE');
Total Blocks............................768
Total Bytes.............................6291456
Unused Blocks...........................118
Unused Bytes............................966656
Last Used Ext FileId....................1
Last Used Ext BlockId...................57225
Last Used Block.........................10

高水位线在 768-118 + 1 = 651块 处。

查询在HWM之上的空闲blocks数量:
SQL> select empty_blocks from user_tables where table_name='MY_OBJECTS2';

EMPTY_BLOCKS
------------

哎哎。。我擦,没有出现结果,然后去oracle的参考文档,查到了下面的一些话:

EMPTY_BLOCKS* NUMBER   Number of empty (never used) data blocks in the table

Note:

Columns marked with an asterisk (*) are populated only if you collect statistics on the table
with the ANALYZE statement or the DBMS_STATS package.(意思就是说先经过分析,才能查出数据来。)
那好吧,既如此,咱们就给分析一下吧。用如下语句分析:

SQL> analyze table my_objects3 compute statistics;
表已分析。

SQL> select empty_blocks from user_tables where table_name='MY_OBJECTS3';
EMPTY_BLOCKS
------------

   118

这下出来了。。。有118个块没有存储过数据。。。

继续用我们今天开篇介绍的语句alter table 。。。。deallocate unused 消除没有使用的数据块。

SQL> alter table my_objects3 deallocate unused;
表已更改。

SQL> analyze table my_objects3 compute statistics;
表已分析。

SQL> select empty_blocks from user_tables where table_name='MY_OBJECTS3';
EMPTY_BLOCKS
------------
           6

SQL> exec show_space(p_segname=>'MY_OBJECTS3' ,p_owner=> 'SYS' ,p_type=>'TABLE');
Total Blocks............................656         ——与之前的统计比,减少了112块。
Total Bytes.............................5373952
Unused Blocks...........................6          ——与之前统计比,减少了118-6=112块。
Unused Bytes............................49152
Last Used Ext FileId....................1
Last Used Ext BlockId...................57225
Last Used Block.........................10

PL/SQL 过程已成功完成。

高水位线在 656-6+1=651 处 ,此时,表的高水位线没有变化,其实我们完全可以理解,因为alter table 。。 deallocate unused ; 只是清除的HWM之上的块。这一点在我们开始就说明了。在此也得到了验证。

2、在HWM 之下的空闲block

当数据插入到一个block后,那么HWM就移动到这个block之上了。然后后续的操作又将这个block中的数据删除了,那么,这个block实际上是空闲的。但是这些block位于HWM之下,所以是不会出现在empty_blocks 列中的。那么这样的,在HWM之下的块过多会影响性能的,就像前面讨论过的 table full scan 中看到的那样。

下面测试:

SQL> delete from my_objects3 where rownum<15000;

已删除14999行。

SQL> exec show_space(p_segname=>'MY_OBJECTS3' ,p_owner=> 'SYS' ,p_type=>'TABLE');
Total Blocks............................656
Total Bytes.............................5373952
Unused Blocks...........................6
Unused Bytes............................49152
Last Used Ext FileId....................1
Last Used Ext BlockId...................57225
Last Used Block.........................10

PL/SQL 过程已成功完成。
 可以看到删除了之后没有任何变化。这是因为删除操作不会对HWM 进行移动。

3、在assm中HWM下的blocks使用情况

运用一个脚本:
http://blog.csdn.net/changyanmanman/article/details/8209377 (第二个过程)

执行效果:
SQL> exec show_space_assm('MY_OBJECTS3','SYS');
BEGIN show_space_assm('MY_OBJECTS3','SYS'); END;
*
第 1 行出现错误:
ORA-10614: Operation not allowed on this segment            ——在system表空间上不允许执行这个过程。
ORA-06512: at "SYS.DBMS_SPACE", line 159
ORA-06512: at "SYS.SHOW_SPACE_ASSM", line 28
ORA-06512: at line 1

查看报错原因,如此说来我们只能从user 表空间上重新创建一个表,然后来分析。

SQL> conn scott/liu123
已连接。

SQL> create table my as select * from all_objects ;
表已创建。

SQL> SET SERVEROUTPUT ON
SQL>  exec show_space_assm('MY','SCOTT');
free space 0-25% blocks:................0
free space 25-50% blocks:...............0
free space 50-75% blocks:...............0
free space 75-100% blocks:..............0
Full Blocks:............................545
Unformatted Blocks:.....................0

PL/SQL 过程已成功完成。
可以看到这些块,全是满的块。

SQL> delete from my where rownum < 15000;   ——删除一些块之后继续测试
已删除14999行。

SQL>  exec show_space_assm('MY','SCOTT');
free space 0-25% blocks:................0
free space 25-50% blocks:...............0
free space 50-75% blocks:...............0
free space 75-100% blocks:..............206
Full Blocks:............................339
Unformatted Blocks:.....................0
PL/SQL 过程已成功完成。
SQL>

这下一看就知道,一些块里的数据被删除了,这样一来不满的块也就多了。。。

闲着没事,又执行了一些show_space 空间统计的过程:

SQL> exec show_space(p_segname=>'MY' ,p_owner=> 'SCOTT' ,p_type=>'TABLE');
Total Blocks............................640
Total Bytes.............................5242880
Unused Blocks...........................77
Unused Bytes............................630784
Last Used Ext FileId....................7
Last Used Ext BlockId...................264
Last Used Block.........................51
PL/SQL 过程已成功完成。

简单算了一下,总共用的块数是640-77=563 ; 但是通过show_space_assm过程算出来的块是:206+339=545 。 这两个相差18个块。目前不知道这18个块是怎么回事,如果有懂的同学请各位留个言哈。。

2、如何降低HWM

8i以前的版本中,如果需要降低segment的HWM.  可以采用两种方法,分别是 exp/imp  和 CTAS 

(ctas 参照博客:http://blog.csdn.net/changyanmanman/article/details/8211253)这两种方法大家都很熟悉,不必多说,下面介绍3种降低HWM 的方法,顺便学习这三个命令。

1、move 命令

从8i开始,oracle提供了move命令。通常使用这个命令将一个table segment 从一个tablespace 移动到另一个tablespace。move实际上是在block之间物理的copy数据。

书上做了一个实验,经过alter table table_name move; 命令操作之后,表的blockid 会发生变化,也就是说会重新移动表的数据,重新拷贝 block 到新的块。很明显只要blockid变化了。。那rowid 就肯定的。。不是原来的了。。。

下面我们通过my 表删除行进行测试:

SQL> select table_name from user_tables;
TABLE_NAME
------------------------------
MY
SALGRADE
BONUS
EMP
DEPT

SQL> select count(*) from my;
  COUNT(*)
----------
     23954

SQL> set serveroutput on
SQL> exec show_space(p_segname=>'MY' ,p_owner=> 'SCOTT' ,p_type=>'TABLE');
Total Blocks............................640
Total Bytes.............................5242880
Unused Blocks...........................77
Unused Bytes............................630784
Last Used Ext FileId....................7
Last Used Ext BlockId...................264
Last Used Block.........................51
PL/SQL 过程已成功完成。

SQL> delete from my where rownum<1000;
已删除999行。

SQL> exec show_space(p_segname=>'MY' ,p_owner=> 'SCOTT' ,p_type=>'TABLE');
Total Blocks............................640
Total Bytes.............................5242880
Unused Blocks...........................77
Unused Bytes............................630784
Last Used Ext FileId....................7
Last Used Ext BlockId...................264
Last Used Block.........................51
PL/SQL 过程已成功完成。

SQL> alter table my move;
表已更改。

SQL> exec show_space(p_segname=>'MY' ,p_owner=> 'SCOTT' ,p_type=>'TABLE');
Total Blocks............................384
Total Bytes.............................3145728
Unused Blocks...........................46
Unused Bytes............................376832
Last Used Ext FileId....................7
Last Used Ext BlockId...................520
Last Used Block.........................82
PL/SQL 过程已成功完成。

这下可以看到HWM 下降了。

以下是alter table 中move子句的完整语法,这里介绍其中用的几点:

move [ONLINE]

   [segmetn_attributes_clause]

   [data_segment_compression]

  [index_org_table_clause]

  [{ LOB_storage | varray_col_properties}

     [ { LOB_storage_clause | varray_clo_properties } ] ...

 ]

 [parallel_clause]

可以使用move将一个table从当前的tablespace上移动到另一个tablespace上例如:

alter table  t  move tablespace tablespace_name;

还可以用move来改变table已有的block 的存储参数,例如:

alter table t move storage (initial 30k next 50k) ;

另外move操作也可以用来解决table上的行迁移问题。

使用move的一些注意事项

a、table上的index需要重建(rebuild): 这个自然不用说了,数据块拷贝,rowid 改变,索引自然失效。、

b、move时对table的锁定:对 my 表进行move操作的时候,查询v$locked_objects视图可以发现,my表上加了exclusive lock。

c、move时空间使用:当前的tablespace中需要1倍于table的空闲空间以供使用。 

2、DBMS_REDEFINITION

这个包是从9i开始引入的,用来做table的联机重组和重定义,可以通过这种方法在线的重组table、来移动table中的数据,降低HWM,修改table的存储参数,分区等。。

这个操作要求table上有一个主键,并要求预先创建一个带有要求修改该的存储参数的table,以便保存重新组织后的数据。保存重新组织的数据的table叫临时表。他只在重新组织期间被使用,在操作完成后可以被删除。

使用DBMS_REDEFINITION 包需要如下权限:

create any table;

alter any table;

drop any table;

lock any table;

select any table;

在dbms_redefinition上执行操作。使用dbms_redefinition重组table一般是这样几个步骤:

(1)使用dbms_redefinition. can_redef_table()验证所选择的table能够被重建。

(2)创建空的临时表,确保这个临时表定义了主键。

(3)使用dbms_redefinition.start_redef_table()进行table重组。

(4)在临时表上创建触发器、索引和约束,一般来说,这些对象与源表中的是一致的,但是名称必须不同。同时要确保所有外键约束不可用。在重组结束时,所有这些对象将替换定义在源表上的对象。

(5)使用dbms_redefinition.finish_redef_table() 完成重组过程。在这期间,源表将会lock较短的时间。

(6)删除临时表。

3、shrink 命令

如果表空间时自动段空间管理的(ASSM),就可以使用这个shrink 命令来缩小段,降低HWM,需要强调的是这个命令仅对assm 管理模式的段空间有效。

下面直接上测试过程吧:

SQL> select tablespace_name,block_size,extent_management, allocation_type,segment_space_management from dba_tablespaces where tablespace_name='ASSM';

TABLESPACE_NAME      BLOCK_ SIZE    EXTENT_MAN      LLOCATIO     SEGMEN
------------------------------       ----------                   ----------                 ---------             ------
  ASSM                                 8192                         LOCAL              SYSTEM          AUTO

SQL> create table my tablespace  assm as select * from all_objects;        ——创建测试表
表已创建。

SQL> select  count(*) from my;

  COUNT(*)
----------
     47231

在各个块中删除一些数据行,这样可以在各个数据块中出现空的地方,块就有很多不满的了。。。
SQL> delete from my where object_name like '%c%'  ;
已删除20950行。

SQL> delete from my where object_name like '%u%';
已删除4689行。

SQL> delete from my where object_name like '%a%' ;
已删除5644行。

SQL> set serveroutput on
SQL> exec show_space(p_segname=>'MY' ,p_owner=> 'SYS' ,p_type=>'TABLE');
Total Blocks............................768
Total Bytes.............................6291456
Unused Blocks...........................98
Unused Bytes............................802816
Last Used Ext FileId....................8
Last Used Ext BlockId...................776
Last Used Block.........................30
PL/SQL 过程已成功完成。

SQL> exec show_space_assm('MY','SYS');
free space 0-25% blocks:................0
free space 25-50% blocks:...............7
free space 50-75% blocks:...............12
free space 75-100% blocks:..............452
Full Blocks:............................179
Unformatted Blocks:.....................0
PL/SQL 过程已成功完成。

现在看来由于我们刚才的删除操作,有了很多的块不满了。。下面可以用shrink命令来重组了。。

在进行shrink之前,表必须支持 行移动,这个很重要的,可以用下面的命令实现:

SQL> alter table my enable row movement;
表已更改。

现在可以用以下命令来降低my表的HWM:

SQL> alter table my shrink space;
表已更改。

SQL> exec show_space(p_segname=>'MY' ,p_owner=> 'SYS' ,p_type=>'TABLE');
Total Blocks............................208
Total Bytes.............................1703936
Unused Blocks...........................1
Unused Bytes............................8192
Last Used Ext FileId....................8
Last Used Ext BlockId...................264
Last Used Block.........................79
PL/SQL 过程已成功完成。

SQL> exec show_space_assm('MY','SYS');
free space 0-25% blocks:................1
free space 25-50% blocks:...............0
free space 50-75% blocks:...............0
free space 75-100% blocks:..............1
Full Blocks:............................193
Unformatted Blocks:.....................0
PL/SQL 过程已成功完成。

可以看到HWM下降了。。。原来不满的数据块都基本变成满满的了。。。

最后一点:可以在shrink table的同时shrink这个table上的index:

alter table my shrink space cascade;

shrink命令内部的原理:

shrink命令内部的原理到底是什么样的?我们知道,在move命令操作的时候,所有的行的rowid都发生了变化,table所位于的block的区域也发生了变化,但是所有行物理存储的顺序是没有变化的,所以我们得到的结论是oracle以block为单位进行了block间的数据copy。

那么shrink后,可以发现部分行的rowid发生了变化,同时部分行的物理存储顺序也发生了变化,而table所位于的block区域却没有变化,这说明,shrink只移动了table其中的一部分行的数据来完成释放空间,而且这个过程是在table当前的使用的block中完成的。

shrink的时候oracle移动数据是以行为单位的。oracle从当前table的存储的最后一行数据开始移动,从当前table最先使用的block开始搜索空间,也就是最后一行会尽量往表块的最前面的空闲处插入。接着倒数第二行继续向前插入。。。一直重复这个过程。

shrink命令注意的问题:

a、shrink后index是否需要rebuild:在执行完成shrink收缩操作之后,通过查询语句:

select index_name,status from user_indexes where  index_name = '被收缩表生的index_name';

可以发现,index 的状态位 valid , 估计shrink 在移动行数据时,也一起维护了index上相应的数据rowid信息。可以认为,这是对move操作后需要 rebuild index的改进。但是如果一个table上的index数量较多,因为维护index的成本也是较高的,所以shrink过程中用来维护index的成本也会比较高。

b、shrink时对table的锁定: 在对table shrink时,会对table进行怎样的锁定呢?当对表my 进行shrink操作时,查询v$locked_objects 视图可以发现,表 my 上加了row-X(SX)的lock:

SQL > select  object_id , session_id, oracle_username,locked_mode from v$locked_objects;

OBJECT_ID       SESSION_ID     ORACLE_USERNAME        LOCKED_MODE

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

55422                     153                             DLINGER                                     3

SQL > select object_id from user_object where object_name = 'MY_OBJECTS';

OBJECT_ID

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

 55422

可以看出,当table进行shrink时,对table是可以进行DML操作的。

3、shrink对空间的要求:shrink不会像move一样,它不需要额外的空闲空间。

3、其他可以移动HWM 的操作

1、insert append

但是用 /* +insert append */ into 向一个table中插入数据时,oracle不会在HWM以下寻找空间,而是直接移动HWM, 从 EMPTY_BLOCKS 中获得要使用block空间,来满足这一操作对blocks的需要。

实验测试表中,我们建立了all_objects 的映像表,然后删除掉里面的全部数据, 再向表中 insert into (注意这个顺序) 1000条数据,重新分析表,发现HWM没有移动,还是在建表时的位置。

继续delete所有数据,重新用insert /*+append*/ into 语句插入数据,执行show_space过程分析,发现HWM向后移动了。而不会在前面空的块中插入数据。

下面我们比较一下insert into  和 insert /*+append* / into 的效率问题:

经过建空表,插入测试发现 insert into 会比 insert /*+ append*/ into 慢很多,这是为什么呢?

最后提一下,在使用 insert /*+ append*/ into  时,oracle会生成表级独占锁(对表加上 exclusive 模式的TM 锁),可以阻断其他会话的DML操作。

时间: 2023-11-28 06:08:48

oracle点知识——HWM(高水位线) 下的相关文章

oracle点知识 ——HWM(高水位线) 上

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

Oracle 降低高水位线的方法

Oracle  降低高水位线的方法  高水位(HIGH WARTER MARK,HWM)好比水库中储水的水位,用于描述数据库中段的扩展方式.高水位对全表扫描方式有着至关重要的影响.当使用DELETE删除表记录时,高水位并不会下降,随之导致的是全表扫描的实际开销并没有任何减少. 例如,首先新建一张空表,大小占用64K,然后插入数据直到表大小变为50G,此时使用DELETE删除所有的数据并且提交,这个时候查询表的大小的时候依然是50G,这就是因为表的高水位没有释放的缘故,而在这时如果使用"SELEC

INITIAL参数设置导致TRUNCATE TABLE不能降低高水位线案例

在一个数据库使用下面SQL找出了一批需要降低高水位线的表,其中有几个表没有数据,于是我打算用TRUNCATE来降低高水位线HWM SELECT a.owner,        a.segment_name,        a.segment_type,        a.tablespace_name,        a.blocks              "real block",        a.bytes / 1024 / 1024 "realSizeMB&quo

高水位线和全表扫描

   高水位线好比水库中储水的水位线,用于描述数据库中段的扩展方式.高水位线对全表扫描方式有着至关重要的影响.当使用delete 操作 表记录时,高水位线并不会下降,随之导致的是全表扫描的实际开销并没有任何减少.本文给出高水位线的描述,如何降低高水位线,以及高水 位线对全表扫描的影响.   一.何谓高水位线    如前所述,类似于水库中储水的水位线.只不过在数据库中用于描述段的扩展方式.     可以将数据段或索引段等想象为一个从左到右依次排开的一系列块.当这些块中未填充任何数据时,高水位线位于

高水位线条款:中国基金激励的现实选择

在美国对冲基金中广泛应用的高水位线条款,如果能以适当的方式引入到我国开放式基金中,对促进我国开放式基金的发展或将起到很好的推动作用 文/李曜 史丹丹 在不到十年的时间里,美国的对冲基金从1000家迅速增长到7000家,资产规模在2007年时超过1.5万亿美元.为什么对冲基金如此成功? 西方学术界发现,对冲基金与公募基金的重要区别之一就是高水位线条款(high water marks, 以下简称HWM),这是以美国为代表的西方私募资产管理业,特别是对冲基金业管理费设计的一个关键技术条款.HWM条款

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

oracle|性能|优化 Oracle Freelist和HWM原理探讨及相关性能优化 中兴通讯重庆研究所 游波   关键词:Freelist,HWM,存储参数,段,块,dump,优化 文章摘要:    近期来,FreeList的重要作用逐渐为Oracle DBA所认识,网上也出现一些相关的讨论.本文以FreeList为线索对Oracle的存储管理的原理进行较深入的探讨,涉及Oracle段区块管理的原理,FreeList算法等.而与FreeList密切相关的一个重用特性HWM,与sql性能密切相

Oracle基础知识-数据迁移

我们常需要对Oracle数据库进行迁移,迁移到更加高级的主机上.迁移到远程的机房上.迁移到不同的平台下 一.exp/imp: 这也算是最常用最简单的方法了,一般是基于应用的owner级做导出导入. 操作方法为:在新库建立好owner和表空间,停老库的应用,在老库做 [sql] view plaincopyprint? exp user/pwd owner=XXX file=exp_xxx.dmp log=exp_xxx.log buffer=6000000 传dmp文件到新库,在新库做 [sql

Oracle基础知识-启动Oracle常见疑难问题分析

实例和数据库的启动与关闭是DBA的重要职责之一.只有打开数据库,其他用户才能对数据库中的数据进行操作.一旦数据库关闭,便不能对其操作.对于DBA们来说,关闭和重新启动数据库以便优化.调整应用程序的运行是经常碰到的事情.如果用户已经进入了数据库,使用SHUTDOWN IMMEDIATE 或SHUTDOWN ABORT命令来执行关闭数据库,则用户将失去连接,直到数据库重新启动.经常关闭和启动会对数据库性能造成一定的影响,当然也会影响到用户对数据库的使用.本文从管理数据库的角度来分析在Oracle启动

Oracle基础知识-Oracle不同的启动关闭方式

Oracle中不同启动和关闭方式的区别 Oracle数据库提供了几种不同的数据库启动和关闭方式,本文将周详介绍这些启动和关闭方式之间的区别连同他们各自不同的功能.一.启动和关闭Oracle数据库 对于大多数Oracle DBA来说,启动和关闭Oracle数据库最常用的方式就是在命令行方式下的Server Manager.从Oracle 8i以后,系统将Server Manager的任何功能都集中到了SQL*Plus中,也就是说从8i以后对于数据库的启动和关闭能够直接通过SQL*Plus来完成,而