[hive]外部分區表結構變更後查詢爲空問題解決

0X00 前提

本意是想見想記錄以前遇到過的問題,由此引申出一些思考,關於目前hadoop等大數據生態,或多或少都會存在一些問題,重要是我們認清現實之後,熱愛我們的選擇。
關於技術上的成長,除了下文所說的要保持謙遜外,還在於積累和思考。
問題解決是怎樣的不重要的,重要的是自己的總結,我也是想趕緊把這些記錄下來以免以後忘了可惜,畢竟這個小問題也是兩年前遇到過的,今日想起,順手寫下來。

數倉技術選型:hive+sqoop1.4.4
場景:數倉中ods增量表由於上游db表變更緣故,需要對應地增加兩個字段,一般使用alter table table_name add columns(column_name type comment '');的方式來直接在hive中增加字段。但由於上下游之間信息傳達、溝通不到位,導致在上游db的源表已經增加表字段數天後,數倉相關部門才收到通知,故數倉的變更除了對錶修改之外,還需要對歷史數據的刷新補位。
問題:新增字段後需要對增量錶的歷史分區進行數據刷新。使用sqoop同步數據到hive中覆蓋增量表的分區,增量表爲天分區外部表。在檢驗歷史數據同步情況的時候,發現新增字段的數據顯示爲空。即外部分區表新增字段刷新歷史分區數據後查詢爲空。

0X01 過程

分析:

  1. 通過對比,新增字段後同步產生的分區裏面,數據能夠正常查詢,但問題出現在歷史分區的查詢。
  2. 由於是外部表,我們可以在hive中通過dfs -fs -cat的方式直接查看錶數據文件(sqoop在map之後生成的hdfs文件),發現文件中最後兩列(新增列,此處以txt格式文件爲例)是有數據的。由此可知問題在於查詢時對應列無法加載/被識別,而非同步有問題
  3. 通過調通sqoop來試驗,發現將同步到的數據文件放到指定的其他hdfs路徑下,並通過ALTER TABLE table_name ADD PARTITION (partCol = 'value1') location 'loc1'; 方式新增分區,發現數據能夠正常查詢。如果將歷史分區的路徑作爲新分區的數據文件查詢路徑,也即新分區和某個歷史分區共用同一個數據路徑下的數據文件時,通過指定分區名的方式分別查詢兩個分區的數據(select × from table_name where partition_name='XXX'),發現新分區能夠正常查詢,歷史分區依舊有問題。由此可見,查詢出現的問題與數據文件本身無關,或者說數據文件本身是完好的
  4. 綜上,我們可以認爲是表的結構或者說是表的元數據更新有問題導致的歷史分區數據在刷新之後無法正常查詢。

0X02 解決

解決:
表元數據更新問題由於集中在歷史分區,可以先通過drop partition的方式清理舊的元數據信息,然後再重新新建表分區ALTER TABLE table_name ADD PARTITION (partCol = 'value1') location 'loc1'; 。這樣歷史分區的數據就可以正常查詢了。

0X03事後思考

由於hive數據的加載模式,它是會將表的元數據(記錄在hive的管理RMDB,一般是mysql)和表數據(HDFS或者本機文件)分開存放,並且一般的ddl、dcl語句只對元數據進行檢查、修改,並不會對錶的數據進行強校驗。而且不同分區的元數據分開記錄,新增字段之後,只對之後的分區產生效應(比如10個字段增加到12個字段),而歷史分區的元數據記錄裏面依舊記錄着這些歷史分區對應的字段只有10個,這也就是爲什麼需要我們把歷史分區drop掉之後在重新新建,因爲這樣可以把另外2個新增字段信息添加到分區元數據記錄中。
分佈式的存儲結構、處理思想,決定了數據在存放、計算時是需要劃分小塊後進行的,這樣會導致了一些問題,比如塊之間可能由於跨機器甚至跨機房導致的網絡通訊滯後、元數據記錄由於多次更改產生多條不一致記錄,這些對會對數據的元數據一致性管理造成挑戰。這也是造成這種加字段、刷新數據後,數據查不出來的問題的原因,而這類原因往往會比較超出我們的思維習慣,讓第一次遇見這種問題的程序員感到匪夷所思,但我們如果能帶入到分佈式的思想中去思考,就能明朗。
所以,由此也引申出來了CAP原則,NoSQL或者是說分佈式系統能且只能滿足其中兩個原則。往往我們需要通過了解分佈式系統/組件/工具的特性,理清我們的需求之後再去選用適用的系統組件,而不是做出類似讓hive去做事實計算(實際上是劃分較小時間區間去做近實時的數據更新而已)、讓hbase去做數據關聯分析、讓kafka做持久化存儲的騷操作。理論上是可行,我本人也曾實踐過前兩種,但引出來的bug、問題、解決這些問題的腦力、時間成本遠遠超出你重新部署一塊新的大數據組件比如spark,妄圖通過一招鮮打遍天下無敵手是最蠢的,抽象到哲學層面可以一招走天下,但畢竟你是在工程層面,你還是考慮實踐的成本和效果。
我認爲程序員保持謙遜是很重要的,即使你很牛。謙虛可以讓你認清你的環境、你所處的層面、你所要面對的挑戰和收益、你缺點和擅長。我認識一個10年以上的oracle數據庫開發,對已oracle本身無比熟悉,也很認同oracle的思想。但是總是跳不出這個框架,口頭禪是“你這個大數據怎樣怎樣,以前oracle怎樣怎樣就處理好了,一點都不好用”。我這麼寫不是爲了引戰,hadoop也好oracle也好,其實都是工具、都有各自的優缺點,只要系統的優點是剛好能滿足我當前最高優先級的需求且其缺點暴露出來的問題是當下能夠容忍的,那麼就是最好的工具,不管缺點會被放大多少倍,在這裏田忌賽馬、黑貓白貓纔是中心思想。我也遇到“如何使用SQL快速實現聚類算法”的靈魂提問,這已經不是田忌賽馬了,是關公戰秦瓊了。
是的,黑貓白貓理論是應用層面最好的標準。前提是保持謙遜、保持認真,不要鬧關公戰秦瓊的笑話,這樣我們才能不斷做出大部分是有利自身、科技、社會的迭代。

0X04事後再補充

你以爲文章已經結束了嗎?我還想再寫幾句。
我記得上大學學計算機的時候我們老師就給我們講了二分法,對於大部分人都是大一才接觸計算機且聽完老師講解完還一知半解。老師當時語重心長:“現在沒搞懂沒關係,後面你一定要背下來,代碼怎麼實現的、思想是怎樣的。”
我到現在也沒背下來代碼。但是思想我確實在一次次工作實踐(打臉)中領悟了。二分其實更多的是告訴我們面對一個旁大的集合、旁大的任務,我們要去做適當的分解拆分成一份份小集合、小問題,然後逐個攻破。(還有遞歸思想也很重要)
工作中遇到的MVC分層、數倉分層、分佈式思想無不散發出問題切分的光輝。
但是切分出來的小問題、任務都會越來越具象,以至於其執行步驟的通用性在下降,所以出現差異化,這也是既有NoSQL又有關係型DB的緣故、既有離線批處理又有流式計算、既有OLTP又有OLAP的原因。
衆多組件的堆砌,無異增加了運維的成本,所以有了微服務、有了離線計算和流計算融合的Flink、有了NoSQL和SQL融合的谷歌Spanner、PingCAP的TiDB。
是謂合久必分、分久必合。
我們可以看到,科技發展史本身和歷史進程是吻合的,很多技術、架構並不是一開始設計好的,而是根據需要不斷改進、重新設計出來。往往對這個結論,有很多人持有不同看法,畢竟時間天馬行空的科學研究、創造也很多,它們並不一定“接地氣”。
其實它們也是符合我們需要的,只是目前自身所處環境、從衆心理等困住思維的翅膀,我們暫時無法看到它的必要性。5G出來的時候也有很多人認爲沒有必要,畢竟現在4G已經足夠快了甚至過剩了,現在看來,並不是網絡傳輸技術超前了,是其他方面落後了。
對於成功,一個人的奮鬥固然重要,但也要考慮歷史的進程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章