大分割槽表的手工並行優化

jeanron100發表於2013-11-08
這段時間飽受大分割槽表的效能之苦,碰到最大的一個分割槽表有1個t左右,操作起來每個細節都需要格外小心,我這次和大家分享的案例應用的分割槽表不是很大,有80G左右。但是這個分割槽主要分割槽比較多,有將近2000個左右的分割槽。
舉一個案例來說明一下。
現在要做以下下幾件事,要保證要當機時間儘可能短。
為了方便起見,我暫定現在有4個DB instance,叫par01,par02,par03,par04.
1.需要對par01的資料執行Update語句,根據條件更新(update操作可能會移動分割槽),
2.然後把par01的資料匯出來
3.重新對par01,par02,par03,par04進行分割槽
4.選擇性的把資料匯入到par01,par02,par03,par04
所以看以上步驟最終目的就是把par01的資料更新以後重新分佈到par01,par02,par03,par04上去。
除了以上的4個步驟,我還設想了以下的實現方式,但是實際操作的時候,發現不好控制,而且可能在網路頻寬和磁碟空間上都有一定的要求。
1)採用db link,在par01上建立par02,03,04的db link,然後對Par01,02,03,04分割槽後,資料的複製直接使用db link來做。--&gt這個部分對網路頻寬有很高的要求,而且比較糾結的一點事不好控制進度。如果有任何異常,只能重新開始。
2)採用臨時表,建立4個臨時表,設定為Nologging,然後使用insert/*+append */的方式根據需要插入資料。然後匯出,然後重新匯入到02,03,04上。->-會佔有大量的磁碟空間,相當於複製了一份資料的映象。比如庫有200G,就得額外需要200G的資料空間。需要耗費更長的時間。


首先是第一個部分。
1.需要把par01的資料執行Update若干語句(update操作可能會移動分割槽),
這種update操作對於oracle來說是敏感的。
需要enable row movement才可以。
因為備份已經充足,所以特意對錶設定了nologging.
然後按照開發提供的指令碼執行update,(有獎金8個sql語句)結果update整整跑了快6個小時。幸虧是測試環境預演,能夠提前發現很多的問題。
可以接受的時間範圍是30分鐘左右。所以只能想辦法最大限度的壓縮時間。
首先能想到的是parallel,但是通過測試 parallel dml也有諸多限制,而且效果也不明顯。
最後採用的方法是:par01有上千個partition,可以把每個partition看成獨立的一張表,然後對每個Partition來執行相應的Update,然後在此基礎上根據High_value進行劃分,來決定採用多少個個視窗並行的去跑Update。
sql語句大體如下
update test partition(parxxxxx) set  xxxx where xxxxx;
最後根據資料情況和High value我開了5個視窗並行的跑update,效果很明顯。最後跑了將近半個小時,中間根據一定的頻率來commit,效能確實提高了不少。

2.然後把par01的資料匯出來,
大家對於資料匯入匯出,首先都是expdp/impdp,但是在這個場景裡,不太妥當,而且有一定的風險,最後決定使用exp/imp
原因如下:
1.我們所用的庫是從10.2.0.5.0手工升級到11.2.0.2.0的。對於expdp/impdp有一些已知11g的bug提到會導致資料泵hang住。
2.par01,par02,par03,par04的網路環境很好,如果使用expdp/impdp需要配置相應的directory和使用者許可權,而且需要把dump檔案拷貝到各個服務端目錄下,需要耗費大量的時間,而且拷貝80多G的dump檔案也需要準備足夠的空間。如果直接在par01上進行匯入,不需要配置,就方便度多了。
3.匯出需要生成幾個獨立的dump檔案。採用的方法如下。
exp xxxx file=par01_xxxxxx.dmp log=par01_xxxxx.log statistics=none grants=n constraints=n indexes=n tables=xxxx query=\"where code in \(xxx,xxx,xxx\)\" buffer=9102000
expdp在這種情況下沒有明顯的優勢,首先query選項啟用,direct就沒作用了,開了並行,等了好一會,貌似Hang住了,
最後採用的方法是:採用匯出分割槽的方式,根據資料量和業務情況,把匯出工作分成5個單獨的程式來跑,每個程式會匯出指定的分割槽
比如  thread1:分割槽par_001~par_005
       thread2:分割槽par_100~par_105
檢視系統的負載,匯出時cpu都是滿載的,效果應該和expdp的並行效果差不多,但是控制要靈活。
最後統計結果,本來需要100分鐘以上的任務,最後用了將近30分鐘就全部導完了。

3.重新對par01,par02,par03,par04進行分割槽
需要對Par01,02,03,04的分割槽進行重新的組織。比如原來表只有100個可能根據需要得分成200個分割槽了,而且分割槽名稱也有要求。

這個地方可能有兩種實現,
一種是把分割槽都drop掉,只留一個max pattition,然後split partition
另一種方法是把分割槽不斷的進行merge,最後合併成一個max parition.
我最終選用的是第一種方法,因為比較直觀簡單,重新分割槽的時候步驟很有規律,我生成了動態sql來刪除分割槽,只保留預設的max partition.
這個部分多說一句,有的朋友可能建議不刪資料了,直接根據需要split partition,生成指定的分割槽,我嘗試了這種方法,速度太慢。可能有大量的資料會從各個partition間不斷的move>

4.選擇性的把資料匯入到par01,par02,par03,par04
這個部分基於步驟2,獨立的匯入,時間也好控制。
比如說par02這個分割槽比較大,我匯出的時候就生成了兩個dump檔案,然後匯入的時候,就可以在par02上分兩個獨立的匯入程式操作。

以上是自己的一些總結。也對比了一些其他優化的案例。有些不足,還希望大家多多指教。



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-776144/,如需轉載,請註明出處,否則將追究法律責任。

相關文章