1. 程式人生 > >采用Kettle分頁處理大數據量抽取任務

采用Kettle分頁處理大數據量抽取任務

ont pen -m rownum red 對數 target ktr 無法使用

作者:Grey

原文地址: http://www.cnblogs.com/greyzeng/p/5524614.html

需求:

將Oracle數據庫中某張表歷史數據導入MySQL的一張表裏面。

源表(Oracle):table1

目標表(MySQL):table2

數據量:20,000,000

思路:

由於服務器內存資源有限,所以,無法使用Kettle一次性從源表導入目標表千萬級別的數據,考慮采用分頁導入的方式來進行數據傳輸,即:

根據實際情況設置一個每次處理的數據量,比如:5,000條,然後根據總的數據條數和每次處理的數據量計算出一共分幾頁,

假設總數據量有:20,000,000,所以頁數為:20,000,000/5,000=4,000頁

註: 若存在小數,小數部分算一頁,比如:20.3算21頁

步驟:

根據需求的條件,首先對數據進行分頁:

數據量:20,000,000

每頁數據量:5,000

頁數:4,000

源表(Oracle):table1

目標表(MySQL):table2

主流程:transfer_table1_to_table2.kjb

技術分享圖片

流程說明:
transfer_table1_to_table2.kjb: 主流程

build_query_page.ktr: 構造頁數遊標

loop_execute.kjb: 根據頁數來執行數據導入操作

我們分別來看各個部分的構成:

build_query_page.ktr: 構造頁數遊標

這一步中,我們需要構造一個類似這樣的數據結構:

技術分享圖片

其中P_PAGE是表頭,其余為頁碼數,

註: 在這裏取頁碼數我通過這個表的rownum來構造

SQL:

select rownum as P_PAGE from mds.mds_balances_hist where rownum<=4000

具體實現如下圖:

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

loop_execute.kjb: 根據頁數來執行數據導入操作

在上一步中,我們構造了頁數,在這步中,我們遍歷上一步中的頁碼數,通過頁碼數找出相應的數據集進行操作,

其中包括set_values.ktr和execute_by_page.ktr兩個轉換

loop_execute.kjb具體實現如下:

技術分享圖片

set_values.ktr:表示獲取從上一步中獲得的頁數

技術分享圖片

execute_by_page.ktr:表示根據頁數進行數據導入操作

技術分享圖片

其中query_by_page采用Oracle經典三層嵌套分頁算法:

SELECT b.rn,b.* FROM

(

SELECT A.*, ROWNUM RN

FROM (SELECT * FROM table1) A

WHERE ROWNUM <= (${VAR_P_PAGE}*5000)

) b

WHERE RN >= ((${VAR_P_PAGE}-1)*5000+1)

技術分享圖片

註: ${VAR_P_PAGE}為每次獲取的頁碼數。

select_field為設置需要導入的列名:

技術分享圖片

技術分享圖片

output_target目的是輸出到目標表table2:

技術分享圖片

因為要遍歷上一次執行的結果,那麽需要在transfer_table1_to_table2.kjb的loop_execute.kjb中做如下設置:

技術分享圖片

最後,執行transfer_table1_to_table2.kjb即可。

總結:

通過上述方法,我們可以很好的解決內存不足的情況下,大數據量在不同的數據庫之間的導入工作。

FAQ:

  • 在Kettle導入大量數據的過程中,可能會出現連接斷開的現象:

http://forums.pentaho.com/showthread.php?74102-MySQL-connection-settings-at-java-level

(Idle connection timeout if we keep kettle idle for 8hours).

解決辦法:

技術分享圖片

采用Kettle分頁處理大數據量抽取任務