1.什么是高水位?(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操作。

---------也就是说进行增删操作只会上涨,不会下跌!!!

2.select 特性和高水位的关系

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

----------所以就有人经常会说我的表中明明没有一条数据,但是执行select扫描怎么会那么慢呢,这个时候里面的奥秘就在于高水位线了!

 

降低Oracle高水位线的方法

删除了数据,空间不释放。---oracle 存储会在连续的空间。

1 执行alter table table_name shrink space;(可释放数据库和磁盘空间空间,大表可同时降低表自身和表空间的高水位线,小表则只可以降低表自身的高水位线,原因不详)
注意,此命令为Oracle 10g新增功能,执行该指令之前必须允许行移动 alter table table_name enable row movement;

2 复制要保留的数据到临时表t,drop原表,然后rename临时表t为原表

3 用EXP导出后,删除原表/表空间,之后用IMP重新导入(验证成功)

--方法一.

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');--查看索引状态是否生效

 

--方法二.

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。

方法三:

CREATE TABLE table_name_1 AS SELECT  *  FROM  table_name;

TRUNCATE TABLE table_name;

INSERT INTO table_name SELECT * FROM table_name_1;

弊端:麻烦,耗时

方法四:

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

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