Oracle的高水位线

一、什么是水位线 所有的oracle段都会有一个在段内容纳数据的上线,把这个上限成为“high water mark”,这是一个标记,用来说明已经有多少没有使用的数据块分配给这个段,原则上high water mark只会增大,不会减小,即使delete将表中的数据全部删除,high water mark还是原值,这就使得high water mark就像水库的历史最高水位,但是如果使用truncate,该表的high water mark就会被重置成0.   二、数据库操作的影响 1)全表扫描通常要读出HWM标记的所有属于该表的数据库快,即使该表没有任何数据 2)即使HWM以下有空闲的数据库块,在插入时使用的是HWM以上的数据块,此时HWM会自动增大   三、如何知道一个表的HWM? 1)首先对表进行分析 ANALYZE TABLE <TABLENAME> ESTIMATE/COMPUTE STATISTICS 2)SELECT BLOCKS,EMPTY_BLOCKS,NUM_ROWS     FROM USER_TABLES    WHERE TABLE_NAME = <TABLENAME> SELECT BLOCKS,--水位线        EMPTY_BLOCKS,--从来没有使用过的数据块        NUM_ROWS   FROM USER_TABLES WHERE TABLE_NAME = 'TP_WLJR0005'  备注:blocks列代表该表中曾经使用过的数据库块的数目,即水位线        empty_blocks代表分配给该表,但是在水位线以上的数据库块,即从来没有使用过的数据块   三、oracle表段中的高水位线HWM 在oracle的存储中,高水位线在日常的增删改查中只会上涨,不会下降 1.先得明白select的查询特性:select查询时候,会对表中数据进行一次扫描,并不是说数据块有多少数据就扫描多少数据,其决定因素:高水位线以下的数据。     例:新建A表,这时高水位线是0,所以这时查询速度就极快,然后A表插入1000万条数据,这时高水位已经提到了1000W的级别,再次查询的时候,对表中数据扫描就会按照实时的高水位线以下进行扫描。如果delete把数据全部删除,但是高水位线依旧在1000W的级别,查询时候仍然会按照1000W的高水位线进行扫描。     这就是为什么有时候表中数据很少,但是查询速度很慢,其原因就是因为该表的高水位线决定的。 2.降低高水位线:使用truncate语句进行删除表中数据,相当于重新新建了表,不仅把数据清空,而且把高水位线拉低至0。     适用于数据量大的临时表   四、修正oracle的高水位线 在oracle中,执行delete操作并不会降低高水位线,导致查询性能降低。 降低高水位线的操作   1.执行表重建指令 alter table table_name move; 在线转移表空间ALTER TABLE ...MOVE TABLESPACE...,其中MOVE后面不跟着参数也可以,默认还是原来表空间,MOVE后记住重建索引。 如果以后还要继续向这个表增加数据,没有必要MOVE,只是释放出来的空间只能这个表用,其他的表或者segment无法使用该空间 2.执行alter table table_name shrink space.压缩碎片,回收高水位线。 注意:此命令为Oracle 10g新增功能,再执行该命令之前必须允许alter table table_name enable row monement; 3.赋值要保留的数据到临时表,drop原表,然后rename临时表为原表名。 4.alter table table_name deallocate unused 5.truncate     开发环境试验 选择降低高水位线的方式:shrink space 原因:move确实整理碎片的效率很高,但是不移动高水位线,而且还要重建索引;shrink space整理碎片不仅能降低高水位线,而且不需要重新建索引,但是使用shrink space之前一定要进行行迁移 move不能移动高水位线的原因:alter table move不能修改rowid,且shrink space能修改rowid,但是要先进行行迁移   1.先把碎片率高的表找出来 select 'drop table ' || segment_name || ' purge;',        sum(bytes) / 1024 / 1024 Mbytese   from user_segments a, user_tables b where segment_type = 'TABLE'    and a.segment_name = b.TABLE_NAME    and b.COMPRESSION = 'DISABLED' group by segment_name, COMPRESSION order by sum(bytes) / 1024 / 1024 desc;   SELECT table_name,        ROUND((blocks * 8/1024), 2) "高水位空间 M",        ROUND((num_rows * avg_row_len / 1024/1024), 2)  "真实使用空间 M",        ROUND((blocks * 10 / 100) * 8, 2) "预留空间(pctfree)  M",        ROUND((blocks * 8 - (num_rows * avg_row_len / 1024)  -blocks * 8 * 10 / 100), 2) "浪费空间 M",        ((blocks * 8-(num_rows * avg_row_len /  1024))/1024)/(blocks * 8/1024) "浪费空间 %"   FROM user_tables WHERE table_name = 'TP_WLJR0005'; 在高水位和真实使用空间之间的差距=浪费空间,产生浪费空间的原因是高水位线的上涨,真实使用空间变小(大量的delete造成的),当浪费空间%达到25%就需要整理了。   2.开启行迁移 行迁移补充:在ORACLE中,当执行一条UPDATE 语句时候,可能会使一行的长度增加,从而其实不能放在一个数据块,这是Oracle就会自动寻找一个能容纳下该行的数据块,如果能找到,那么Oracle会把该行的数据全部搬到新的数据块中,只留下一个指针(Point)指向新的块,但是行标识(rowid)没有变化,依旧是之前的数据块。当访问这条记录时候,Oracle先会找到原来的数据块,然后通过指针指向新的数据块。 alter table TP_WLJR0005 enable row movement;--开启行迁移   3.碎片压缩 alter table table_name shrink space cascade;--进行压缩   4.关闭行迁移 alter table table_name disable row movement;--关闭行迁移   脚本:Oracle的高水位线
--查看该用户下表段空间情况
select 'drop table ' || segment_name || ' purge;',
       sum(bytes) / 1024 / 1024 Mbytese
  from user_segments a, user_tables b
 where segment_type = 'TABLE'
   and a.segment_name = b.TABLE_NAME
   and b.COMPRESSION = 'DISABLED'
 group by segment_name, COMPRESSION
 order by sum(bytes) / 1024 / 1024 desc;
--查看某个表的高水位线情况
SELECT table_name,
       ROUND((blocks * 8/1024), 2) "高水位空间 M",
       ROUND((num_rows * avg_row_len / 1024/1024), 2) "真实使用空间 M",
       ROUND((blocks * 10 / 100) * 8, 2) "预留空间(pctfree) M",
       ROUND((blocks * 8 - (num_rows * avg_row_len / 1024) -blocks * 8 * 10 / 100), 2) "浪费空间 M",
       ((blocks * 8-(num_rows * avg_row_len / 1024))/1024)/(blocks * 8/1024) "浪费空间 %"
  FROM user_tables
 WHERE table_name = 'TP_WLJR0005';
--开启行迁移 
alter table tp_wljr0005 enable row movement;
--压缩碎片
ALTER TABLE TP_WLJR0005 SHRINK SPACE CASCADE;
--查看表段空间
select sum(bytes)/1024/1024 from user_segments where segment_name='TP_WLJR0005';
--收集统计信息 
exec dbms_stats.gather_table_stats('TPS','TP_WLJR0005',CASCADE=>TRUE); --在toad里面执行
--关闭行迁移
alter table tp_wljr0005 disable row movement;

 

                                       
上一篇:Centos 创建软Raid +扩容


下一篇:Linux文件的元数据信息