1. 程式人生 > >採用Kettle分頁處理大資料量抽取任務

採用Kettle分頁處理大資料量抽取任務

需求:

將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).

解決辦法:


原文地址: http://greyzeng.com/2016/10/31/big-data-etl/