天天看點

海量資料遷移之分區表批量insert性能改進

在平時的工作中接觸到的分區表一般都比較大,而且分區也少則幾十,多則幾百,上千。

在資料遷移的時候,分區表的遷移更是塊大骨頭,因為資料量太大,而且有些分區表中還有一些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隻會鎖定一個相應的分區。而且考慮加入并行,可能性會好很多。

按照這個思路,就沒有嚴格意義上的大表了,我們都可以切分再切分。

繼續閱讀