Kettle增量更新設計技巧


摘要:本文主要討論一些在ETL中設計增量更新的方法和技巧。
 
ETL中增量更新是一個比較依賴與工具和設計方法的過程,Kettle中主要提供Insert / Update 步驟,Delete 步驟和Database Lookup步驟來支持增量更新,增量更新的設計方法也是根據應用場景來選取的,雖然本文討論的是Kettle的實現方式,但也許對其他工具也有一些幫助。本文不可能涵蓋所有的情況,歡迎大家討論。
 
應用場景
 
增量更新按照數據種類的不同大概可以分成:
1.         只增加,不更新,
2.         只更新,不增加
3.         即增加也更新
4.         有刪除,有增加,有更新
其中1,2, 3種大概都是相同的思路,使用的步驟可能略有不同,通用的方法是在原數據庫增加一個時間戳,然后在轉換之后的對應表保留這個時間戳,然后每次抽取數據的時候,先讀取這個目標數據庫表的時間戳的較大值,把這個值當作參數傳給原數據庫的相應表,根據這個時間戳來做限定條件來抽取數據,抽取之后同樣要保留這個時間戳,並且原數據庫的時間戳一定是指定默認值為sysdate當前時間(以原數據庫的時間為標准),抽取之后的目標數據庫的時間戳要保留原來的時間戳,而不是抽取時候的時間。
   對於第一種情況,可以使用Kettle的Insert / Update 步驟,只是可以勾選Don’t perform any update選項,這個選項可以告訴Kettle你只會執行Insert步驟。
對於第二種情況可能比較用在數據出現錯誤然后原數據庫有一些更新,相應的目標數據庫也要更新,這時可能不是更新所有的數據,而是有一些限定條件的數據,你可以使用Kettle的Update步驟來只執行更新。關於如何動態的執行限定條件,可以參考前一篇文章。
第三種情況是更為常見的一種情況,使用的同樣是 Kettle的Insert / Update 步驟,只是不要勾選Don’t perform any update選項。
第四種情況有些復雜,后面專門討論。
 
 

 

對於第1,2,3種情況,可以參考下面的例子。
這個例子假設原數據庫表為customers ,含有一個id , firstname , lastname , age字段,主鍵為id , 然后還加上一個默認值為sysdate的時間戳字段。轉換之后的結果類似:id , firstname , lastname , age , updatedate .整個設計流程大概如下:
 
1
其中第一個步驟的SQL大概如下模式:
Select max(updatedate) from target_customer ;
你會注意到第二個步驟和第一個步驟的連接是黃色的線,這是因為第二個table input步驟把前面一個步驟的輸出當作一個參數來用,所有Kettle用黃色的線來表示,第二個table input的sql 模式大概如下:
Select field1 , field2 , field3 from customers where updatedate > ?
后面的一個問號就是表示它需要接受一個參數,你在這個table input下面需要指定replace variable in script選項和execute for each row 為選中狀態,這樣,Kettle就會循環執行這個sql ,執行的次數為前面參數步驟傳入的數據集的大小。
 
2
 
 

 

關於第三個步驟執行insert / update步驟需要特別解釋一下,
 
3
 
 

 

Kettle執行這個步驟是需要兩個數據流對比,其中一個是目標數據庫,你在Target table 里面指定的,它放在The keys to look up the values(s)左邊的Table field 里面的,另外一個數據流就是你在前一個步驟傳進來的,它放在The keys to look up the value(s)的右邊,Kettle首先用你傳進來的key在數據庫中查詢這些記錄,如果沒有找到,它就插入一條記錄,所有的值都跟你原來的值相同,如果根據這個key找到了這條記錄,kettle會比較這兩條記錄,根據你指定update field來比較,如果數據完全一樣,kettle就什么都不做,如果記錄不完全一樣,kettle就執行一個update步驟。所以首先你要確保你指定的key字段能夠確定一條記錄,這個時候會有兩種情況:
1.      維表
2.      事實表
維表大都是通過一個主鍵字段來判斷兩條記錄是否匹配,可能我們的原數據庫的主鍵記錄不一定對應目標數據庫中相應的表的主鍵,這個時候原數據庫的主鍵就變成了業務主鍵,你需要根據某種條件判斷這個業務主鍵是否相等,想象一下如果是多個數據源的話,業務主鍵可能會有重復,這個時候你需要比較的是根據你自定義生成的新的實際的主鍵,這種主鍵可能是根據某種類似與sequence的生成方式生成的,
事實表在經過轉換之后,進目標數據庫之前往往都是通過多個外鍵約束來確定一條記錄的,這個時候比較兩條記錄是否相等都是通過所有的維表的外鍵決定的,你在比較了記錄相等或不等之后,還要自己判斷是否需要添加一個新的主鍵給這個新記錄。
上面兩種情況都是針對特定的應用的,如果你的轉換過程比較簡單,只是一個原數據庫對應一個目標數據庫,業務主鍵跟代理主鍵完全相同的時候完全可以不用考慮這么多.
 
有刪除,有增加,有更新
 

 

首先你需要判斷你是否在處理一個維表,如果是一個維表的話,那么這可能是一個SCD情況,可以使用Kettle的Dimension Lookup 步驟來解決這個問題,如果你要處理的是事實表,方法就可能有所不同,它們之間的主要區別是主鍵的判斷方式不一樣。
事實表一般都數據量很大,需要先確定是否有變動的數據處在某一個明確的限定條件之下,比如時間上處在某個特定區間,或者某些字段有某種限定條件,盡量較大程度的先限定要處理的結果集,然后需要注意的是要先根據id來判斷記錄的狀態,是不存在要插入新紀錄,還是已存在要更新,還是記錄不存在要刪除,分別對於id的狀態來進行不同的操作。
處理刪除的情況使用Delete步驟,它的原理跟Insert / Update 步驟一樣,只不過在找到了匹配的id之后執行的是刪除操作而不是更新操作,然后處理Insert / Update操作,你可能需要重新創建一個轉換過程,然后在一個Job 里面定義這兩個轉換之間的執行順序。
如果你的數據變動量比較大的話,比如超過了一定的百分比,如果執行效率比較低下,可以適當考慮重新建表。
另外需要考慮的是維表的數據刪除了,對應的事實表或其他依賴於此維表的表的數據如何處理,外鍵約束可能不太容易去掉,或者說一旦去掉了就可能再加上去了,這可能需要先處理好事實表的依賴數據,主要是看你如何應用,如果只是簡單的刪除事實表數據的話還比較簡單,但是如果需要保留事實表相應記錄,可以在維表中增加一條記錄,這條記錄只有一個主鍵,其他字段為空,當我們刪除了維表數據后,事實表的數據就更新指向這條空的維表記錄。
 
 

 

定時執行增量更新
 

 

可能有時候我們就是定時執行更新操作,比如每天或者一個星期一次,這個時候可以不需要在目標表中增加一個時間戳字段來判斷ETL進行的較大時間,直接在取得原數據庫的時間加上限定條件比如:
Startdate > ? and enddate < ?
或者只有一個startdate
Startdate > ?   (昨天的時間或者上個星期的時間)
這個時候需要傳一個參數,用get System Info步驟來取得,而且你還可以控制時間的精度,比如到天而不是到秒的時間。
當然,你也需要考慮一下如果更新失敗了怎么處理,比如某一天因為某種原因沒有更新,這樣可能這一天的記錄需要手工處理回來,如果失敗的情況經常可能發生,那還是使用在目標數據庫中增加一個時間字段取較大時間戳的方式比較通用,雖然它多了一個很少用的字段。
 
 

 

執行效率和復雜度
 

 

刪除和更新都是一項比較耗費時間的操作,它們都需要不斷的在數據庫中查詢記錄,執行刪除操作或更新操作,而且都是一條一條的執行,執行效率低下也是可以預見的,盡量可能的縮小原數據集大小。減少傳輸的數據集大小,降低ETL的復雜程度
 
 

 

時間戳方法的一些優點和缺點
 

 

優點:  實現方式簡單,很容易就跨數據庫實現了,運行起來也容易設計
缺點:浪費大量的儲存空間,時間戳字段除ETL過程之外都不被使用,如果是定時運行的,某一次運行失敗了,就有可能造成數據有部分丟失.
 
 

 

其他的增量更新辦法:
增量更新的核心問題在與如何找出自上次更新以后的數據,其實大多數數據庫都能夠有辦法捕捉這種數據的變化,比較常見的方式是數據庫的增量備份和數據復制,利用數據庫的管理方式來處理增量更新就是需要有比較好的數據庫管理能力,大多數成熟的數據庫都提供了增量備份和數據復制的方法,雖然實現上各不一樣,不過由於ETL的增量更新對數據庫的要求是只要數據,其他的數據庫對象不關心,也不需要完全的備份和完全的stand by 數據庫,所以實現方式還是比較簡單的.,只要你創建一個與原表結構類似的表結構,然后創建一個三種類型的觸發器,分別對應insert , update , delete操作,然后維護這個新表,在你進行ETL的過程的時候,將增量備份或者數據復制停止,然后開始讀這個新表,在讀完之后將這個表里面的數據刪除掉就可以了,不過這種方式不太容易定時執行,需要一定的數據庫特定的知識。如果你對數據的實時性要求比較高可以實現一個數據庫的數據復制方案,如果對實時性的要求比較低,用增量備份會比較簡單一點。
 
 

 

幾點需要注意的地方:
1.      觸發器
無論是增量備份還是數據復制,如果原表中有觸發器,在備份的數據庫上都不要保留觸發器,因為我們需要的不是一個備份庫,只是需要里面的數據,較好所有不需要的數據庫對象和一些比較小的表都不用處理。
2.      邏輯一致和物理一致
數據庫在數據庫備份和同步上有所謂邏輯一致和物理一致的區別,簡單來說就是同一個查詢在備份數據庫上和主數據庫上得到的總的數據是一樣的,但是里面每一條的數據排列方式可能不一樣,只要沒有明顯的排序查詢都可能有這種情況(包括group by , distinct , union等 ),而這可能會影響到生成主鍵的方式,需要注意在設計主鍵生成方式的時候較好考慮這一點,比如顯式的增加order排序. 避免在數據出錯的時候,如果需要重新讀一遍數據的時候主鍵有問題.
 
 

 

總結
 

 

增量更新是ETL中一個常見任務,對於不同的應用環境可能采用不同的策略,本文不可能覆蓋所有的應用場景,像是多個數據源匯到一個目標數據庫,id生成策略,業務主鍵和代理主鍵不統一等等,只是希望能給出一些思路處理比較常見的情況,希望能對大家有所幫助。


免責聲明!

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



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