文章出處

       

作者: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).

解決辦法:


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()