最近發現KETTLE抽數越來越慢,特別是增量INSERT/UPDATE的時候,速度已經達到了令人發指的地步(從一個400W數據規模的表中每天增量量抽取30W數據的TRASFORMATION 竟然要20個小時!!!!讀取速率是5條/s......),這個情況是在我的KETTLE工具從3.2升級到7.0版本后發現的,(以前也慢,只是還能接受,升級之后已經到了不改不行的地步了),但是KETTLE是進步的,所以原因還是要從自身找起。
目前為止我發現的導致KETTLE抽取數據慢有以下幾個原因:
A:SPOON 啟動時候內存較小,在spoon.bat這個啟動文件中,配置的有JVM的內存XMX,("%PENTAHO_DI_JAVA_OPTIONS%"=="" set PENTAHO_DI_JAVA_OPTIONS="- Xms8192m" "-Xmx8192m" "-XX:MaxPermSize=4096m"),默認這個是256M,512M 256M, 其中Xms是指JVM初始分配的堆棧的內存,Xmx是指JVM分配的堆棧的內存 (JAVA代碼能涉及到的存儲數據變量的內存)最大是多少,所以XMS必須要<= XMX,XX:MaxPermSize,是指JVM給自己分配的非堆棧內存(供虛擬機程序自己開銷)我的因 為是在服務器上跑,因此改成了8192M\8192M\4096M,這個改不能是無限的加大,需要考慮總的內存大小,一般來說網上參考是最大堆棧內存不超過總內存的3/8有的也說是 一半,總之得有個度。
B:抽數的源數據庫關鍵字段沒有索引,以我這張表為例,我每天需要按照日期(data_update_date)從DB2增量抽取更新數據,但是這個字段沒有建索引,因此也會導致抽數慢。
C:抽數的源數據庫關鍵字段索引在SPOON里面失效,給大家看兩段SQL就知道了:
SQL1:select TO_CHAR(TO_DATE(t_date,'YYYYMMDD')+1,'YYYYMMDD') from delta_table where t_name='~~~'
SELECT * FROM SAPCP1.ZCSSDH053 WHERE REPORT_CREATE_DATE >= ?
SQL2:select t_date from delta_table where t_name='~~~'
SELECT * FROM SAPCP1.ZCSSDH053 WHERE REPORT_CREATE_DATE > ?
兩段SQL執行的都是相同的數據提取過程,但是在REPORT_CREATE_DATE 字段建立索引的情況下,SQL1比SQL2快20倍。原因是用 > 號的時候,索引會失效,而用>=則不會。
於是我在網上搜索了這種明明應該走 但是並沒有走索引的情況(以下是粘貼的)
使用<> (有的時候單獨的使用< 或者>的時候也有可能)
like的時候不能確定最前面的字符 也就是把’%_’的時候
單獨使用復合索引的非前導列
表沒有分析
字符類型不匹配 發生了顯示的或者隱式的轉換或者對索引列進行了運算
使用了 not in 或者 not exist
基於cbo時全表掃描代價小
b-tree索引is not null的時候會走,is not null的時候不會走 位圖的時候都會 復合索引的時候 is not null會 is null時要看前導列
D:目的地數據庫表的索引太多,這個原因顯而易見,因為插入數據的時候會重新更新索引表,索引太多,插入時候會變慢。
E:插入流程中數據COMMIT過程太頻繁,數據插入的COMMIT太頻繁也是很影響效率的,,30W的數據提交300次和提交30次速度顯然是不一樣的,只要你的設置的內存能暫時容得下插入的數據,COMMIT可以盡量設高一點(kettle有限制不能超過50000)
F:INSERT/UPDATE 過程與 表輸入,這兩個流程肯定是后者快很多,但是筆者在實際過程中會遇到一個問題就是,萬一ETL抽數流程的某個環節發生了錯誤,導致ETL后面的流程DUMP掉,要么沒插入要么部分插入,這樣的話,肯定是沒有更新關鍵字段的。(關鍵字段更新是放在所有流程最后一步),這樣的話,當筆者解決掉這個問題重新啟動流程,如果重頭開始,對於INSERT/UPDATE字段沒什么問題,數據重復會進行更新,但是對於表輸入的話,就會有問題,昨天寫入的數據已經存在了,這樣不作處理肯定還會報錯。KETTLE 7.0 解決了這個問題,在JOB層設計的時候提前設定好失敗數據回滾的操作,在回滾的操作里面刪掉已經插入的數據,這樣的話用表輸入就沒有后顧之憂了。
最后,30W數據進過以上優化時間從20個小時縮短到0.5個小時~~我暫時發現這些優化方式,各位高人有其他方法歡迎交流~~~!!!!