根據公司MySQL數據庫中存儲的業務數據,針對用戶相關一些維度,提取用戶相關的屬性字段,其中包括屬性字段直接提取,金額字段的計算提起,日期字段的格式轉換等,最終將一個用戶的各個屬性在頁面進行展現。java
項目使用的是MySQL+Sqoop+Hadoop+Hive進行的離線數據處理,其中大數據相關的框架使用的是CDH平臺集成的。程序員
整個項目中用到了不少知識,好比:shell腳本、Sqoop導出導入語句、hive數據合併、hive數據ETL等等。web
CDH中的Sqoop導出有一個問題,就是導出的時候不顯示錯誤信息,錯誤信息須要在CDH的web頁面中去查看,而控制檯只顯示導出中斷,任務失敗的信息。sql
具體解決方法請參見本人以前的文章:CDH的坑之Sqoop導出數據到MySQLshell
一開始對數據不是很瞭解,選擇了\t做爲數據的分割符,導出的數據在統計的時候出現了問題,字段對應不上,在檢查數據的過程當中,發如今數據中某些字段包含了\t,那麼這個分隔符就不能使用了,果斷的換了豎線「|」,問題暫時獲得瞭解決,爲何說事暫時獲得解決?數據庫
不知道業務方和開發是怎麼定義的數據,就怕後期數據存儲過程當中出現豎線,那麼到時候就又須要換了。編程
爲了實現導出到數據庫中的數據,數據庫中已經存在的,更新,不存在的進行插入,開始爲了順利進行數據導入,在MySQL中建立的表沒有任何約束,那麼在使用Sqoop更新模式的時候,使用了allowinsert模式,可是數據卻全是插入的,沒有實現本人想要的操做。
最後通過一番測試,發現要想實現本人理想的效果,MySQL中的表被指定的update-key字段必須惟一非空才行,讓後將id字段添加爲主鍵,效果實現了。bash
在原始的業務數據中,本公司的訂單表是按照每個月一張進行存儲的,這個須要進行數據合併。架構
數據合併剛開始一直考慮怎麼把全部的數據合併到一張表中去處理,而這個思路直接就擱淺了,好像Sqoop作不到,只能將數據導入到hdfs中再進行合併,若是直接合並的話,新數據又是一個問題,怎麼讓新數據也合併到這個表中?框架
想過使用增量導入,可是問題在於MySQL中的表不是一張,而是一個月一張表。
最後在網上查到了一個方法,那就是外部分區表,將每一個表分別以分區的目錄導入HDFS中,而後在Hive中建立一個外部分區表,而後再將每一個分區添加到表中,這樣全部的數據都合併到了一個庫中。
具體詳情參見本人以前的文章:Hive應用:外部分區表
本公司成立也好多年了,訂單表也堆積了好幾年的數據,那麼在公司發展的過程當中,表中的字段也發生了改變,一些字段的順序發生了改變,增長了一些字段,也刪除了一些字段,這樣在表合併的時候,表格式對不上,最後提取的數據確定不許確。
期初爲了保證數據的完整性考慮,創建一張字段完整的表,將數據導入,但是這樣作,根本不知道那張表是更改過的,期間表設計更改了幾回,這樣作Sqoop的導入語句好像並不能實現。
最後,通過確認,使用到的全部字段,在全部的訂單表中都是存在的那麼就選擇了局部字段導出。
hive中的日期格式轉換比sql的要麻煩一些,sql中使用一個函數就解決的,在Hive中須要使用多個內置函數才能解決,而且仍是嵌套函數,使用的時候注意思路,比較繞。
當所有數據導入以後,進行數據聚合的時候發現,好像出現了無限小數。這個問題困擾了我好長時間,由於數據計算只涉及到簡單的加減法,沒有乘除等更高級的計算,怎麼會出現無限小數呢?
觀察原始數據發現,訂單表中的全部金額都是使用float類型存儲的,忽然想到,計算機不能精確存儲小數,更別提計算的精確性了,之前作web項目的時候數據庫都是採用整數存儲小數,前臺展現的時候再轉化爲小數,沒想到公司的設計這麼的讓人無以言表啊。
那麼發現問題的根本以後,就好解決了,本人在導數據的時候,就將這些小數先轉化爲整數,而後再導入HDFS進行存儲,那麼在計算的過程當中就不會出現不精確的狀況了,前臺使用的時候,再轉化爲小數展現。
導出的過程當中,發現即便使用了MySQL的floor()函數,存儲到HDFS中的數據也是帶着小數點的,這個暫時沒弄明白,不太小數部分都是0就不會影響計算了。
計算結果導出的時候,發現沒有了小數點,很神奇。
在設計了外部分區表以後,發現本公司的數據一共有200個左右的分區,手寫這些分區,還不得寫死啊,就想使用一種方法,讓它本身循環添加,這才符合一個程序員的思想,在考慮中Hql語句確定是不行了,Shell腳本我的感受也不是太好,那麼最後我選擇了Hive的Java JDBC編程來實現這個事情,多是由於本人能夠熟練的使用Java,因此以爲這個比較好用。
利用Java寫循環語句,進行添加便可。
後期我會將這個方法單獨寫一篇文章,到時候將鏈接黏貼過來。
業務須要一個自增的id做爲中間表的惟一標識,那麼hive中好像沒有提供這個方法,通過一番查找,本人用了一個變種的方法,那就是row_number() over()這兩個方法聯用,就會自動生成一個自增的字段。
就單獨寫這兩個方法,不須要多餘的參數,例如:
insert into table user_1 select row_number() over() as id,username,age from user;
在寫shell腳本的時候,發現了寫出的包含Sqoop語句的腳本,直接運行沒有問題,當放入定時列表運行的時候,會報錯,報的是找不到java環境,這種狀況着實讓我頭疼。
後來通過資深的運維大哥告知,在腳本中Sqoop語句以前加入java的環境變量便可解決這個問題,試了以後,果真沒問題,不愧是資深的運維大哥啊。
加入的環境和Linux系統中的java環境變量一致便可,以下:
export JAVA_HOME=java安裝路徑 export PATH=$PATH:$JAVA_HOME/bin #或者 JAVA_HOME=java安裝路徑 PATH=$PATH:$JAVA_HOME/bin export JAVA_HOME PATH
以上就是本人這個項目中遇到的問題,想作好一個項目,須要方方面面的知識來支持,須要仔細認真的考慮,不能有任何遺漏,一旦出現紕漏那麼就是問題爆發的地方。這個項目很簡單,可是暴露出了不少常見的問題,之後再遇到相似的問題以後,就會很快的解決,對本身的知識也有了必定的增加。
我相信,大多數人都有眼高手低的時候,好比:本人上面出現的Sqoop導出的語句,不就是導出嗎,之前用開源框架的時候,什麼問題都會在控制檯暴露出來,但是如今用了CDH就讓本身傻眼了,實踐出真知,亙古不變的真理,人不能犯懶,必定要多嘗試,多實踐。
在此與你們共勉,共同進步!