1. 程式人生 > >Oracle:alter table shrink space壓縮碎片收縮高水位

Oracle:alter table shrink space壓縮碎片收縮高水位

以前的技術:

對於oracle的表,資料庫在日常使用過程中,不斷的insert,delete,update操作,導致表和索引出現碎片是在所難免的事情,碎片多了,sql的執行效率自然就差了,道理很簡單,高水位線(HWL)下的許多資料塊都是無資料的,但全表掃描的時候要掃描到高水位線的資料塊,也就是說oracle要做許多的無用功!在9i的時候,一個很成熟的碎片整理技術。

alter table xxx move    高水位以下合併碎片,不移動高水位
alter table xxx move compress    高水位以下合併碎片,同時壓縮表,不移動高水位

這個move確實整理碎片的效率很高,但是美中不足的是

不移動高水位。而且還要重建索引依稀記得給為了給公司的資料庫節省空間(實際上是監控系統發出資料庫空間佔用過高的警告)。其中幾張大表是日報表,資料增刪改查比較大,碎片也很多,其中實際佔用的空間肯定比高水位的空間小。所以我在剩餘的空間下面做:

1.把需要的資料放到一個臨時表,create table temp_t1 nologging Select /*+parallel(tab n)*/ * from t1 where .....

2.徹底刪了原表,drop table t1 pruge;

3.還原表,ALTER TABLE oldname temp_t1 TO t1 ;

4.重建索引,create index index_name on t1(...);

過程很複雜很耗時間。

因此oracle在10g哦時候提供了shrink space碎片整理功能,不僅能整理碎片還可以收縮高水位,索引也不需要重建。

alter table move 由於不能修改rowid(物理位置的一個id)所以無法降低高水位,而alter table shrink space 是可以修改rowid的所以在使用之前一定要開啟行遷移:alter table OM_SERV_SUMMARY_xxxx enable row movement; 

自動過程的思路:

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;

安表的空間大小排序找出來,不支援壓縮表哦。

先分析:

exec dbms_stats.gather_table_stats(user,'T1',CASCADE=>TRUE); ==這個分析很耗時間可以設定estimate_percent來調整分析的量。

如果與之前的分析時間差距太大也需要重新分析:

select table_name,last_analyzed from user_tables order by last_analyzed desc nulls last; where table_name = 'OM_SERV_SUMMARY_xxxxxx';

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 = 'OM_SERV_SUMMARY_xxxxxx';

在高水位和真實使用的空間之間的差距=浪費空間,而產生浪費空間的原因是高水位的上漲,真實使用的空間變小(大量的delete)而造成的,而這樣也會產生大量的碎片。浪費空間 %大於25就需要整理了。

2.開啟行遷移

開啟之前程式需要記錄這個表原來的情況,好在壓縮完後回覆原來的模樣:

select row_movement into vc_movement from user_tables where table_name='OM_SERV_SUMMARY_xxxxx';

rowid物化檢視必須在壓縮操作之後重建所以需要開啟行遷移:

alter table OM_SERV_SUMMARY_xxxxx enable row movement; 

3.進行壓縮

alter table OM_SERV_SUMMARY_xxxxx shrink space cascade;

連同索引一起壓縮,比move方便多。

再根據實際情況關閉行遷移

alter table OM_SERV_SUMMARY_xxxxx disable row movement; 

查看錶段空間下降許多

 select sum(bytes)/1024/1024 from user_segments where segment_name='OM_SERV_SUMMARY_xxxxx';

不過在批量實踐當中,在分析的過程上面耗上很多的資源,所以實踐當中可以根據自己的業務邏輯來分析這一張表的碎片情況,技術和業務的結合,效率更佳。