1. 程式人生 > 其它 >大分割槽表的手工並行優化

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

這段時間飽受大分割槽表的效能之苦,碰到最大的一個分割槽表有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來做。-->這個部分對網路頻寬有很高的要求,而且比較糾結的一點事不好控制進度。如果有任何異常,只能重新開始。 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上分兩個獨立的匯入程序操作。 以上是自己的一些總結。也對比了一些其他優化的案例。有些不足,還希望大家多多指教。