2011-10-29 40 views
0

我有一個新的挑戰,即從Oracle數據庫加載約100M行並將它們插入遠程MySQL數據庫服務器。Java ETL過程

我分了問題二:

  1. 負責將數據加載到MySQL服務器的服務器端REST服務器;
  2. 負責加載Oracle數據源的客戶端Java應用程序。

在Java方面,我使用普通的JDBC加載分頁內容並通過網絡將其傳輸到服務器。這種方法效果很好,但它使代碼繁瑣,而且不能很好的擴展,因爲我自己使用Oracle的ROWNUM進行分頁..... WHERE ROWNUM> x和ROWNUM < y。

我現在已經通過Annotations映射了我的實體,並嘗試了Hibernate的StatelessSession。該代碼更可讀和乾淨,但性能更差。

我聽說過ETL工具和SpringBatch,但我不太瞭解它們。 有沒有其他解決這個問題的方法?

在此先感謝。

UPDATE

感謝您的寶貴建議。 我選擇使用SpringBatch從Oracle數據庫加載數據,因爲環境非常緊張,我無法訪問Oracle的工具集。 SpringBatch是trie和真實的。 對於數據寫入步驟,我選擇使用MySQL的LOAD DATA INFILE來編寫記錄塊,正如你所說的那樣。 REST服務處於中間狀態,因爲出於安全原因它們彼此隱藏。

+0

只需使用spring批處理。不要發明一些東西來解決這個問題。如果您有任何SQL Server框位於SSIS附近,那麼您也可以爲此做好這項工作。 – Deleted

回答

5

100M行相當多。您可以通過多種方式進行設計:REST服務器,JDBC讀取,Spring Batch,Spring integration,Hibernate,ETL。但底線是:時間

無論您選擇哪種架構,您最終都必須在MySQL中執行這些INSERT。您的里程可能會有所不同,但只是爲了給您一個數量級:每秒插入2K,需要半天的時間以100M行填充MySQL(source)。

根據同一來源LOAD DATA INFILE可以處理大約25K插入/秒(大約10倍多一個小時的工作)。

說作爲一個數據的這樣的量說我建議:

  • 轉儲Oracle表使用產生人類可讀的內容(或計算機可讀機Oracle數據庫工具,但你必須能夠解析它)

  • 使用盡可能快的工具解析轉儲文件。也許grep/sed/gawk/cut就夠了嗎?

  • 產生與MySQL LOAD DATA INFILE兼容(這是很可配置的)目標文件

  • 導入使用上述命令

在MySQL的文件當然,你可以用漂亮和可讀做到這一點在Java中代碼,單元測試和版本。但有了這些數據,你需要務實。

這是初始負載。之後,大概春季批次將是一個不錯的選擇。如果可以的話,嘗試將應用程序直接連接到兩個數據庫 - 再次,這會更快。另一方面,出於安全原因,這可能是不可能的。

如果你想變得非常靈活並且不直接將自己綁定到數據庫中,那麼在Web服務(REST也很好)的背後公開輸入(Oracle)和輸出(MySQL)。 Spring集成將幫助你很多。

+1

或者,使用JDBC從Oracle檢索記錄,並將它們格式化爲'LOAD DATA INFILE'到文件或文件序列。可能比使用oracle原生工具慢一點,但是你跳過一步並仍然使用加載數據文件的速度,這可能是更耗時的因素。 – extraneon

+0

優秀的答案 –

2

您可以使用Scriptella在數據庫之間傳輸數據。這裏是一個XML轉換文件的例子:

<!DOCTYPE etl SYSTEM "http://scriptella.javaforge.com/dtd/etl.dtd"> 
<etl> 
    <connection id="in" url="jdbc:oracle:thin:@localhost:1521:ORCL" 
       classpath="ojdbc14.jar" user="scott" password="tiger"/> 

    <connection id="out" url="jdbc:mysql://localhost:3306/fromdb" 
       classpath="mysql-connector.jar" user="user" password="password"/> 
    <!-- Copy all table rows from one to another database --> 
    <query connection-id="in"> 
     SELECT * FROM Src_Table 
     <!-- For each row executes insert --> 
     <script connection-id="out"> 
      INSERT INTO Dest_Table(ID, Name) VALUES (?id,?name) 
     </script> 
    </query> 
    </etl>