關於降低高水位線的嘗試(r3筆記47天)
在前一段時間,生產環境中有幾個很大的分割槽表,由於存在太多的碎片,導致表裡的資料就幾十條,但是查詢的時候特別慢。很明顯是高水位線導致的問題。 一般來說這類問題,使用備份->truncate->insert的方式比較保守,不適用於線上操作。 而在10g開始的一個新特性shrink算是一個比較理想的方案,按照新特性的預期,速度也是很快的,而且是線上操作。可以分批釋放表中的冗餘空間。 所以做了一個嘗試,在生產系統中使用這個新特性來降低高水位線。 生產中的表pub_log,sub_log都是分割槽表,分割槽數不多,幾十個左右。 首先使用shrink需要先設定表為enable rowmovement,這個操作會導致和這個表對應的包體失效。 可以使用shrink space compact先來壓縮空間,然後在空閒時段使用shrink space來降低高水位線,但是shrink的操作對於基於函式的索引還是受限的。所以使用的時候需要考量一下。 需要降低高水位線的表是PUB_LOG,SUB_LOG,所在在簡單準備之後,寫了如下的指令碼。
alter session force parallel ddl parallel 8; --設定了並行 alter table PUB_LOG enable row movement; --啟用row movement alter table PUB_LOG shrink space compact; --先壓縮表的空間 alter table PUB_LOG shrink space; --降低表的高水位線 alter index PUB_LOG_PK shrink space compact; --對索引也可以設定同樣的操作。 alter index PUB_LOG_PK shrink space; alter table PUB_LOG disable row movement; alter table SUB_LOG enable row movement; alter table SUB_LOG shrink space compact; alter table SUB_LOG shrink space ; alter index SUB_LOG_PK shrink space compact; alter index SUB_LOG_PK shrink space; alter index SUB_LOG_1IX shrink space compact; alter index SUB_LOG_1IX shrink space ; alter table SUB_LOG disable row movement;
在測試環境中做測試的時候,時間還是很快的,在5分鐘以內完成了所有的操作。
然後指令碼提交給客戶去執行,結果晚上就接到電話,說第一步操作 alter table PUB_LOG shrink space compact 執行了快3個小時,還沒有執行完。客戶最後kill了那個session.
在第二天查這個問題的時候發現,在shrink space compact的同時,有幾個session正在執行update,delete操作,執行還是比較頻繁的。
看來shrink的操作還是需要謹慎,在生產環境中可能涉及的操作場景更為複雜。最後評估之後還是轉為truncate的方式了。
truncate的操作步驟比較老套,但是在操作的時候還是有不少的細節。
首先是備份
可以使用exp/expdp的方式,如果資料量不大,可以採用使用表級備份。
我先嚐試了exp的方式,結果發現還是有一些問題,表裡只有68條資料,但是exp的時候,用了1分鐘左右。
Export terminated successfully without warnings.
real 1m7.111s
user 0m0.104s
sys 0m0.065s
INDEX_NAME TABLESPACE INDEX_TYPE UNIQUENES PAR COLUMN_LIST TABLE_TYPE STATUS NUM_ROWS LAST_ANAL G
---------------------- ---------- ---------- --------- --- ------------------------------ ---------- ------ ---------- --------- -
PUB_LOG_PK NORMAL UNIQUE YES BUFFER_ID,PUB_TRX_ID,SOURCE_COMP_ID TABLE N/A 15 23-OCT-14 N
select count(*)from pub_log 速度也是很慢的。
因為索引是buffer_id開頭,最後間接的使用索引,速度一下子就快了很多。
select count(*)from trb1_pub_log where buffer_id in(select buffer_id from trb1_pub_log group by buffer_id);
COUNT(*)
----------
68
Elapsed: 00:00:00.17
最後轉換為exp的方式,時間降低到5秒
time exp xxx/xxx tables=pub_log file=pub_log_bak.dmp query=' where buffer_id in (select buffer_id from pub_log group by buffer_id)' buffer=9102000 statistics=none grants=n indexes=n
real 0m5.064s
user 0m0.039s
sys 0m0.037s
到這一步其實也基本告一段落了,如果有些分割槽表含有lob欄位,匯出速度也還是會慢不少。
再次進行調整,發現使用表級備份還是不錯的。
create table tmp_bak_pub_log nologging as select * from pub_log where buffer_id in (select buffer_id from pub_log group by buffer_id) ;
Elapsed: 00:00:01.69
create table tmp_bak_sub_log nologging as select * from sub_log where queue_id in (select queue_id from sub_log group by queue_id) ; --sub_log含有lob欄位,exp也還是慢不少,使用表級備份就快多了。
Elapsed: 00:00:00.58
備份完成之後,就是truncate
truncate table pub_log reuse storage;
truncate table sub_log reuse storage;
最後insert即可。
insert into pub_log select *from tmp_bak_pub_log;
commit;
insert into sub_log select *from tmp_bak_sub_log;
commit;
總體來說,對於新特性的使用還是要做大量的測試,需要謹慎和保守,對於一些看似簡單的操作也可以精工出細活。