暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

王者归来--Oracle解决高水位线

Oracle优化大师 2018-09-30
2548

        

       好久不见,前段时间私事多。多谢大家都坚持。我会更加努力的;


什么Oracle的高水位线(high water mark 简称:HWM)

       所有的Oracle存储段(segments,在此,为了理解方便,建议把segment作为表的一个同义词)都有一个在段内存放数据的上线,那么我们把这个上线成为“high water mark”或HWM.HWM是一个标记,用来说明已经有多少没有使用的数据块分配给了这个segment。MWM通常增长的幅度为一次5个数据块。原则上MWM只会增大,不会缩小。即使表中的全部数据都删除了,那么HWM还是原值,不会变,由于这个特点,使得HWM就像一个水库的历史最高水位。

       简单的说就像水库里的历史最高水位。 就如刚挖的水库一样里面没有一滴水,那么它的最高水位为0.同理在刚建的新表中由于没有一条数据,所以的高水位是0,随着不断的往里面添加数据,进行增删操作,那么它的高水位就会上涨。 当然也不是说你把表的数据删掉一半,它的高水位就会下降,因为高水位代表历史最高水位。  在Oracle中执行Delete删除操作不会降低高水位。执行truncate操作可以降低高水位,通常能把高水位降到0.  所以为了降低高水位,能尽量使用truncate的就不使用delete操作。

     因此,删除数据建议使用:truncate。


高水位和Select有什么关系

       在Oracle SQL中执行select 操作,引擎会扫描的是高水位以下的全部数据块。所以不是说数据库中存放了多少数据块,就会扫描多少个数据块。现在回想以下,如果是一个新建的表,里面没有数据,那么你执行select 扫描操作,那么高水位线基本就在0上,所以就没有数据块被扫描。扫描的时间就会用的很少。但是现在你往表里插入1000万条数据,然后再执行delete操作,但是由于delete操作不影响高水位线,所以高水位线还是原来的高水位线。


为什么要降低高水位

        就行水库泄洪一样,你会打开水闸把超出最高水位预警线的水消退掉。 那么在Oracle中高水位以下存放的都是数据块,每次全表扫描的时候都会把高水位以下的全部数据库都扫描一边,如此以来就会很浪会资源,响应时间比较长。  反之,如果我们把高水位降低,那么每次全表扫描的时候是不是扫描的数据块是不是就少了。


为什么出来一个低HWM


        在管理段的时候通常有两种方法:手动管理段空间(Manual Segment Space Management )和自动段空间(Automatic Segment Space Management)。

        在手动管理段空间的时候,段中只有一个HWM,但是为什么又会有一个低HWM呢?其实这都是因为自动管理段空间造成的。 在手动管理的时候数据插入到新的数据块中,数据库块就先会被格式化然后等待数据访问,但是在自动管理中呢,数据插入到新的数据块中,数据块并没有被格式化,而是在第一次访问这个数据库块的时候才格式化这个块。所以我们又需要一条水位线,用来标示已经被格式化的快。这条线就叫做低HWM.

       一般来说,低HWM肯定低于HWM.


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


(1)全表扫描通常要读出直到hwm标记的所有的属于该表数据块,及时该表中没有任何数据。

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


如何降低高水位呢

方法 <1>


ALTER  TABLE  table_name MOVE ;--对表重建


ANALYZE  TABLE  table_name COMPUTE  STATISTICS ;--统计分析


注意:对表重建后记得重建表的所有索引


ALTER  INDEX  IDX_table_name  REBUILD ONLINE;


SELECT index_name,

       status

  FROM user_indexes

 WHERE table_name = upper('table_name'); --查看索引状态是否生效


方法 <2>


ALTER TABLE  table_name ENABLE ROW MOVEMENT;--激活行迁移


ALTER TABLE  table_name SHRINK SPACE;--激活表收缩


ANALYZE  TABLE  table_name COMPUTE  STATISTICS ;--统计分析


注意:如果是分区表,将row movement设置为enable,有可能发生行的物理移动,行的rowid会变化,某一行更新时,如果更新的是分区列,并且更新后的列值不属于原来的这个分区,如果开启了这个选项,就会把这行从这个分区中delete掉,并加到更新后所属的分区。相当于一个隐式的触发器,但不会触发Insert/delete触发器。如果没有开启这个选项,更新时就会报错。


在10g之后,整理碎片消除行迁移的新增功能shrink space


格式:alter table <table_name> shrink space [ <null> | compact | cascade ];


compact : 这个参数当系统的负载比较大时可以用,不降低HWM。如果系统负载较低时,直接用alter table table_name shrink space就一步到位了


cascade : 这个参数是在shrink table的时候自动级联索引,相当于rebulid index。


方法 <3>


CREATE TABLE table_name_1

 AS

   SELECT *

   FROM table_name;


TRUNCATE TABLE table_name;


INSERT INTO table_name 

SELECT * FROM table_name_1;


弊端:麻烦,耗时


方法 <4>


新建一个临时表,把数据复制到临时表,然后把源表drop掉,再把临时表重新命名为源表的名字。


弊端,主键.索引等依托于此表的对象需要重建


校验方法:


通过分析比对表块删除数据前后占用变化.


SELECT num_rows,

       blocks,

       empty_blocks

  FROM dba_tables

 WHERE owner = 'SDBMGR'

   AND table_name = 'TABLE_NAME';





谢谢关注,下期更精彩





本文分享自微信公众号 - Oracle优化大师,如有侵权,请联系 service001@enmotech.com 删除。
文章转载自Oracle优化大师,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论