在資料倉庫建設,處理日常業務需求的過程中,經常會遇到各種各樣的問題。在處理更新操作資料時,遇到資料重複問題。前期因為沒考慮到關系型資料庫update操作,把資料同步到hive時有資料重複問題,在業務日常報表分析時,帶來很大困擾。今天就簡單來說一下,遇到這樣的場景該如何處理。其實隻要用到hive的視窗函數即可解決。
業務背景
首先,要來談談為啥會遇到這個問題。如何不結合業務背景讨論這個問題,那麼是毫無意義的。我們公司在建設數倉過程中,使用的是第三方平台,類似阿裡雲這樣的平台。公司購買的第三方産品,省去了底層的開發工作。很多東西,都是已經封裝完成的,拿來使用即可。
資料倉庫建設,使用傳統關系型資料庫進行資料存儲,顯然是不現實的。我們需要把關系型資料庫,如mysql,oracle等庫裡的資料同步到分布式檔案系統(HDFS)上,我們公司使用的是hive這種非關系型資料庫。注意:hive的中繼資料管理使用的是mysql資料庫,但是業務資料都是存儲在HDFS上的。
從關系型資料庫同步資料的時候,第一次選擇全量同步。因為資料量非常大,單個表的資料就幾百G不等。但是後續繼續使用全量同步顯然是不顯示的,隻能考慮使用增量同步,來同步增量資料,使用 修改時間 這個字段進行判斷資料是否為新增資料。
在日常生産中,使用關系型資料庫,大家知道有update更新操作。比如某個使用者的狀态改變以後,隻需要在資料庫中更改這條已經存在的記錄即可。
但是這種更新我們需要實時的同步到hive中,可是hive并沒有update的更新操作。把關系型資料庫中更新的資料同步到hive中,就會存在資料重複的問題。(因為以前可能已經同步過這條資料)。那麼怎麼解決這個問題呢?
曲線救國,選擇出最新的記錄
hive沒有update的更新操作。但是我們可以通過hive的序列函數和視窗函數來解決這個問題,非常簡單。使用row_number函數即可。
hive的row_number函數
row_number函數:會對所有數值,輸出不同的序号,序号唯一且連續,如:1、2、3、4、5、6、7。利用row_number函數的這種特性選擇出其中一條我們需要的記錄即可。
#造一些簡單的資料進行驗證
id update state password username
001 2020-08-03 15:33:24 1 123456 使用者1
002 2020-08-03 12:31:21 1 abcd12 使用者2
003 2020-08-04 09:05:44 1 223wer 使用者3
001 2020-08-04 16:01:35 1 123abc 使用者1
在關系型資料庫,直接對001這條記錄更新,修改對應的密碼即可。但是這條更新記錄會被同步記錄到hive中,這樣就存在兩條記錄。顯然我們要的是最新時間的記錄。使用row_number選擇出最新的記錄。
通過上面的方法即可選擇出最新的一條記錄。在hive中,視窗函數是經常使用的一種函數,用好了視窗函數,平時開發寫sql中會帶來很多友善。
小問題?如果一個查詢語句,有兩個row_number(),而且兩個分組一樣,但排序不一樣,那麼查詢出來的資料會跟着哪個走呢?
比如下面的查詢語句,最後的結果是按照id還是aga進行排行傳回呢?
答案:最後的結果是根據age來進行排行的,也就是根據最外圍的row_number() 進行排行,有興趣的可以自己驗證一下。
往期回顧
|| 資料倉庫,Hive中使用 != 或 <>; 符号進行條件過濾時的坑
|| 大資料倉庫,Hive複雜的資料結構,SQL列轉行操作
|| Hive Sql最常用的時間處理類,都在這裡了
