結合自己工作中的使用和收集的一些經驗,談談對Kettle中的ETL的一些優化。
1. 數據庫方面
1.1 配置連接池
如果業務數據量很多和短連接很多,可以考慮使用數據庫連接池,在這個時候,每次數據庫連接建立和斷開所花費的時間遠長於進行數據庫操作的時間,配置連接池可以更好的利用網絡資源,將連接建立和斷開的開銷降低到最小。因此在大多數情況下,配置Kettle數據庫連接池均可提高ETL的性能,如果沒有配置連接池,那么在數據量大時候很容易出現Error Connecting Database Error。
1.2 數據庫參數優化
defaultRowPrefetch = 200; (default = 10)
這個參數是修改每次從數據庫取回的記錄的行數,默認為10,修改為200后可以減少從數據庫取值的次數。
(Oracle Only) readTimeout = 60;
這個參數是修改從數據庫讀數據時的超時時間,單位是秒,將這個值改大一點可以防止大量數據讀取時的超時問題。
(Mysql Only) useServerPrepStmts=false; rewriteBatchedStatements=true ; useCompression=true ;
1.3 查詢優化
可以使用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優化
1.6 數據庫分組和排序優於ETL分組和排序
在ETL中減少排序和分組的操作,盡量使用數據庫完成排序和分組。在KTR中,數據是使用流的方式在不同的步驟間傳遞數據,使用排序和分組的操作會在這一步阻塞KTR的執行,直到接收到前面所有步驟傳過來的數據為止,導致ETL的運行時間增長,占用的內存增大。
使用Blocking Step也會將流阻塞到這一步,和以上情況類似。
1.7 盡量使用數據庫原生的方式裝載文本文件
如Oracle的sqlloader, mysql的bulk loader步驟。
2. 步驟優化
2.1 調整步驟之間的緩存

這個值的大小需要根據機器的配置來選擇,如果可用內存足夠,一般的設置是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及組件使用、內存使用的預估、監控等方面盡最大可能、全方位的考慮與優化。
參考: