海量資料遷移之分割槽表批次insert效能改進

dbhelper發表於2014-11-26

在平時的工作中接觸到的分割槽表一般都比較大,而且分割槽也少則幾十,多則幾百,上千。
在資料遷移的時候,分割槽表的遷移更是塊大骨頭,因為資料量太大,而且有些分割槽表中還有一些lob欄位,想直接透過sqlldr來遷移還是需要做一些額外的工作。
如果透過datapump分割槽匯出資料,批次匯入,也是一種思路,不過需要考慮好併發的程式。
透過oracle_datapump來做資料的匯入,可能更為靈活,但是不是絕對的。最近就做了一些相關的資料匯入測試,感觸不少。

比如,目前我們需要匯入的兩個大表,一個是memo,一個是charge,分割槽都有200多個。
而且資料分佈不是很均勻。有的分割槽可能資料要多很多。使用oracle_datapump抽取的時候,比如memo表有25G,如果按照100M為一個單位,那麼就要生成250個dump 檔案。每個dump檔案中大概有50多萬條資料,抽取的dump檔案不是基於分割槽的。然後在目標庫中以外部表的形式載入,然後使用insert來做資料插入,啟用8個並行度。匯入的時候速度就不是很理想。平均每個dump檔案需要大約1~2分鐘的時間,甚至更長。就算減少並行度,控制在4左右,速度還是沒有什麼變化。
本來冥思苦想的這個方案效能打了折扣,然後再一次嘗試,限制生成的dump檔案個數,比如memo表有25G,生成80個dump,這樣每個dump檔案就有將近300M左右。這樣每個dump檔案就大概由150萬的資料。還是啟用了同樣的並行,速度就會快很多,一個dump檔案大約在1~2分鐘,dump的個數少了大半,時間就隨之節省了很多。

基於這個問題,我的想法是dump在100M左右的時候,啟用並行不會有什麼大的起色,啟用8個4個,應該和不啟用並行效果是類似的。
如果dump檔案大了很多,如果啟用並行,就會有相應的程式能夠合理的處理一部分資料。
同時,因為memo表是分割槽表,如果做insert插入的時候,一個insert會在每個分割槽上加一個鎖,這樣就是200個多鎖,這個也是很消耗資源的。如果頻繁的做插入,commit動作,就會不斷的去加同樣數量級的鎖,無形中也快拖累載入速度。如果dump檔案較大,還是會加同樣的鎖,但是會在一定程度上使得並行使用的更為充分。可能加鎖的頻率降低了,對系統的負載也會小很多。

如果想有較大的改進的話,我的個人想法就是透過分割槽級別匯出資料,然後在資料插入的時候,也是基於分割槽匯入,這樣就可以同時做多個insert操作,而且每個insert只會鎖定一個相應的分割槽。而且考慮加入並行,可能性會好很多。
按照這個思路,就沒有嚴格意義上的大表了,我們都可以切分再切分。

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

相關文章