Kettle中的ETL優化


結合自己工作中的使用和收集的一些經驗,談談對Kettle中的ETL的一些優化。

1. 數據庫方面

1.1 配置連接池

如果業務數據量很多和短連接很多,可以考慮使用數據庫連接池,在這個時候,每次數據庫連接建立和斷開所花費的時間遠長於進行數據庫操作的時間,配置連接池可以更好的利用網絡資源,將連接建立和斷開的開銷降低到最小。因此在大多數情況下,配置Kettle數據庫連接池均可提高ETL的性能,如果沒有配置連接池,那么在數據量大時候很容易出現Error Connecting Database Error。

1.2 數據庫參數優化

在 數據庫連接面板 - 選項 中,可通過自定義參數來優化自己的ETL,使其適應自己的需求。
defaultRowPrefetch = 200; (default = 10) 

這個參數是修改每次從數據庫取回的記錄的行數,默認為10,修改為200后可以減少從數據庫取值的次數。

(Oracle Only) readTimeout = 60;  

這個參數是修改從數據庫讀數據時的超時時間,單位是秒,將這個值改大一點可以防止大量數據讀取時的超時問題。

(Mysql Only) useServerPrepStmts=false;
rewriteBatchedStatements=true ; 
useCompression=true ;
前兩個參數會讓數據庫重排Insert語句,合並多條插入語句成為一條,提交插入效率。第三個參數表示在傳輸時開啟數據壓縮 ,提高傳輸效率。這些在使用table output的時候很有效,在配置充足且網絡正常的情況下應該可以達到20k~80k的寫入速度。

1.3 查詢優化

對涉及到數據抽取(SQL查詢)的步驟內的SQL,要盡可能的優化,如:查詢條件必須走索引,對表結構優化,結果集中的字段格式約定(避免過長),輸出最小寬度等;

可以使用sql來做的一些操作盡量用SQL。group,merge,stream lookup,split field這些操作都是比較慢的,想辦法避免他們.,能用SQL就用SQL;

避免在索引列上使用函數或計算,在where子句中,如果索引列是函數的一部分,優化器將不使用索引而使用全表掃描;

避免在索引列上使用 NOT和 “!=”,索引只能告訴什么存在於表中,而不能告訴什么不存在於表中,當數據庫遇到NOT和 “!=”時,就會停止使用索引轉而執行全表掃描;

索引列上用 >=替代 >;

另外需要注意,在設計步驟時,需要關注查詢表的數據量,因為一般情況下開發者可能會使用“表輸入組件”將表中的所有結果集抽出再使用其他組件進行處理,如果表的數據量在十萬級別以下,Kettle會支持;但到百萬或者千萬級別的數據量,運行步驟,Kettle的效率將極為緩慢。此時數據處理能在SQL中進行應盡量使用SQL,並將步驟進行分片,才能避免速度緩慢或者內存占用過高。

1.4 提高數據庫操作中的Commit Size(批處理使用)

在寫入數據庫的時候,有一個Commit size的選項,這個值在默認的情況下是1,我們可以根據服務器的性能,將這個值改大一些,通常會改為100以上的值。這個值在寫入量比較大的時候可以顯著提升數據庫的性能,但是並不是越大越好,通常范圍在100〜10000,需要根據實際情況進行配置,具體數值可以根據性能監控的記錄來確定。

這個值從1調整到合適值性能大約可以翻倍,一般情況下也有20%左右的效率提升。

1.5 Insert/Update/Delete優化

Kettle的原作者在他的博客中提到過,盡量不要使用Insert/Update組件,因為這個組件慢的他都受不了,正常情況下在幾百條每秒(對比TableInsert幾萬的速度)。如果必須使用這個組件的時候,那么可以在Insert/Update中勾選Don't perform any updates(不做任何更新操作),然后把錯誤的數據指向一具數據庫更新的操作,這要就把添加和更新分離了開來。根據官網描述,在少量更新大量插入的時候性能可以提高到原來的3倍左右,實測時達不到,可能和數據集有關。
當插入的數據為數據表中的記錄數量10%以上時,首先需要刪除該表的索引來提高數據的插入效率,當數據全部插入后再建立索引。
盡量避免使用update,delete操作,,尤其是update,如果可以把update變成先delete,后insert;
能使用truncate table的時候,就不要使用deleteall row這種類似sql合理的分區,如果刪除操作是基於某一個分區的,就不要使用delete row這種方式(不管是deletesql還是delete步驟),直接把分區drop掉,再重新創建;

1.6 數據庫分組和排序優於ETL分組和排序

在ETL中減少排序和分組的操作,盡量使用數據庫完成排序和分組。在KTR中,數據是使用流的方式在不同的步驟間傳遞數據,使用排序和分組的操作會在這一步阻塞KTR的執行,直到接收到前面所有步驟傳過來的數據為止,導致ETL的運行時間增長,占用的內存增大。

使用Blocking Step也會將流阻塞到這一步,和以上情況類似。

1.7 盡量使用數據庫原生的方式裝載文本文件

如Oracle的sqlloader, mysql的bulk loader步驟。

2. 步驟優化

2.1 調整步驟之間的緩存

KTR是一個流式的處理過程,步驟與步驟之間的數據傳遞是通過緩存來完成的,調整緩存的大小可以對KTR的運行產生明顯的影響。

這個值的大小需要根據機器的配置來選擇,如果可用內存足夠,一般的設置是10000,也就是緩存10000行數據,如果內存比較緊張,可以將該值調小一些,保證不會占用過量內存。

在性能監測時,這也是一個用來找到瓶頸的核心參數。如果某一步的輸入和配置的緩存大小接近,但是輸出很小,那么這一步就是性能的瓶頸。如果緩存大小配置了10000,但是幾乎所有步驟的輸入輸出都只有很低的一個值,比如50,那么,性能的瓶頸就是輸入。

2.2 延遲轉化

很多字段在讀入到最后輸出,實際上都沒有被操作過,開啟延遲轉化可以讓kettle在必要的時候再進行轉化。這里的轉化是指從二進制到字符串之間的轉化,在輸入和輸出都是文本的時候更為明顯。事實上,Select Values在轉化的效率上也高於讀取時直接轉化。

2.3 使用復制並行處理某個步驟

現在的機器都是多核的,使用多CPU並行處理對CPU使用密集的步驟可以提升ETL的執行效率。

在需要並行處理的步驟上,選擇Change Number of Copies to Start, 修改這個值為小於機器核心總數的一個值,一般2〜4就可以滿足要求。

2.4 KTR中,盡量減少步驟的數量

步驟的數量會在影響KTR的執行效率,包含並行處理時復制的數量。KTR中步驟的數量為機器核心總數的3〜4倍最佳,如果超過這個范圍,可以考慮通過減少步驟數量的方式以提高KTR的執行效率。

2.5 不要在Select Values的步驟刪除某個字段

如果在Select Values的步驟刪除某個字段,kettle會需要調整現有的存儲結構,在可以不刪除的時候盡量不要刪除字段。

3. 日志和監控

通過監控知道你的性能瓶頸在哪,可能有時候你使用了不恰當的方式,導致整個操作都變慢,通過觀察kettle log生成的方式來了解你的ETL操作最慢的地方。

4. 其他優化

  • Kettle是Java語言實現的,盡量用大一點的內存參數啟動Kettle
  • 使用Carte管理KJB和KTR減小內存消耗
  • 使用定時器定時處理
  • 使用集群並行運行
  • 使用數據倉庫及緩慢更新進行同步增量更新
  • 遠程數據庫用文件+FTP的方式來傳數據,文件要壓縮

總結下來,當初技術選型時選定Kettle聽到了一些擔心,如開源工具本身的不穩定,大數據量下的低效,吃內存問題等,使用下來,Kettle這個工具本身還是不錯的,但是設計中需要注意對包括數據庫本身、ETL步驟、SQL及組件使用、內存使用的預估、監控等方面盡最大可能、全方位的考慮與優化。

 

 

參考:

https://www.jianshu.com/p/66cefe5208a7

https://blog.csdn.net/smooth00/article/details/64441362


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM