您好,登錄后才能下訂單哦!
本篇內容主要講解“Hive與Spark開發生產中遇到的問題有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Hive與Spark開發生產中遇到的問題有哪些”吧!
生產環境版本 Hive: 1.2.1, Spark: 2.3.2
注意,生成結果是目錄,生成目錄里面的不同文件名不會被覆蓋,因此很容易出現數據double或者沒有覆蓋到數據的問題,比如數據分片原始結果如下:
/mytable/000000_0 /mytable/000000_1 /mytable/000000_2 /mytable/000000_3 ## 新生成的數據只含有 000000_0分片,那么1 2 3分片并不會被刪掉
解決方式:使用目錄上面建立外表insertoverwrite, 如果這個目錄是導入其他系統的目錄文件,可能更致命。注意建立外表時候,如果是分區表,刪除掉分區,然后insert overwrite也會導致數據重復,測試版本2.3.2
//a文件數據內容 //2 10 //2 10 //2 10 //創建管理表 create table t2(id int) partitioned by (dt string); load data local inpath '/xxx/a' // 創建外分區表 create external table t1(id int) partitioned by (dt string); // overwrite分區10 insert overwrite table t1 partition(dt='10') select 1 from t2 where dt=10; //刪除分區10 ALTER TABLE t1 DROP PARTITION(dt='10'); // overwrite 10這個分區 insert overwrite table t1 partition(dt='10') select 2 from t2 where dt=10;
結果顯示6條數據,顯然是異常的,在hive中這個結果是正常的(ps,最后發現是由于組內小伙伴自己調試原因,改了參數,其實默認參數是沒問題的,就是true)
解決方式:
set spark.sql.hive.convertMetastoreParquet=true
set spark.sql.hive.convertMetastoreOrc=true
注意:select
的字段名即使和tableA
中的字段一樣,但是插入順序與字段順序不一樣,那么結果也是有問題的
常見發生情況為 later view
下的select
,以為字段名對了,插入就沒問題,實際上是按順序插入的,即select再插入,也許與底層是mr實現有關系
通過spark.write寫的方式,然后再與表關聯,寫路徑的方式主要有下面兩種,通過參數:mapreduce.fileoutputcommitter.algorithm.version
來控制,
Spark寫入HDFS是依賴于Hadoop的FileOutputCommitter的,它有兩種算法,一種是直接寫到臨時目錄,再copy到輸出目錄,稱之為v1版本,另外一種是直接輸出到結果目錄,稱之為v2版本,輸出性能上v2版本好一點,但是這兩種都不能保證最終一致性,也就是在并發寫,情況下都是有問題的,其中v1是兩階段提交,可以保證讀的時候,不是臟數據
具體可參考:https://blog.csdn.net/u013332124/article/details/92001346
常發生于任務剛啟動,然后停止,又立刻重新調度
注意:離線的事務性比較差,多注意一下,盡量不要立刻重啟任務,讓同一個目錄寫數據的操作同時進行,如果一定要馬上重啟調度任務,解決方式是kill掉任務,刪除_remporay文件即可,離線情況下一致性往往大于性能,拒自己情況選擇v1還是v2版本的提交。
在回溯數據和例行執行任務時候,可能會出現寫數據還沒寫完,回溯的任務將表msck repair ,導致下游任務讀到的數據不完全,跟3問題類似,其中兩個version的提交,在msck repair 之后,都會出現,數據不完全,下游任務就檢測到分區
解決方式:
write + repair —> insert / write + add partition
在hive里面直接寫是支持的,在spark里面會先刪數據分區,然后懶加載才開始讀數據,這樣就導致空指針,空數據問題,解決方法是先cache + 隨便一個action 數據緩存到內存。
注意:一般這樣不建議,除非是剛開始開發的不重要的表,離線的做法是增加version來區分版本,常用在增加字段,修改字段生成邏輯,先增加個version,在新version上來搞,搞完了通知下游切換,或者保證無誤,將version改到老分區。
實際場景中,要盡可能地讓數據跑批冪等,否則會出現在不知情維護情況下出現線上問題,增量表冪等常用處理方式ods_day ≤ 當天
,全量表常用處理方式ods_day=當天
即使并不需要卡這個時間,在當前天修數據,或者回溯時候,就不能保證數據一直有效,不能回溯的數據,查問題會讓你惡心至極。
對于Orc文件格式和Parquet文件格式,從兼容上來說,Spark實現更新一點,Hive稍微舊一點,比如用Spark建立的分區在某些情況寫出現null, empty等問題,可以設置下面兩個參數,開啟使用hive的orc和Parquet格式來建表,這樣Spark和Hive就可以讀到可以同時兼容的數據表了,建議除非一些臨時表,需要落庫的表,可以盡量用Hive的方式來建,建完以后,Spark寫的時候多加下面的參數就不會有兼容問題了
//第一種 set spark.sql.hive.convertMetastoreParquet=true set spark.sql.hive.convertMetastoreOrc=true //第二種 // Spark使用與Hive相同的約定寫parquet數據 .config("spark.sql.parquet.writeLegacyFormat", "true")
20/12/07 19:39:17 ERROR executor.Executor: Exception in task 740.2 in stage 2.0 (TID 5250) org.apache.http.ConnectionClosedException: Premature end of Content-Length delimited message body (expected: 16,384; received: 0)
遇到如圖所示問,從表面展示出來的是,讀文件太高,導致傳輸只傳輸了一半數據,與機器限流有關,就我廠而言,問過bmr維護的人,給的答復是,減少對某一文件的讀取頻率
解決方式:剛開始有些郁悶,離線數據讀難道還有并發問題,其實是限制的在某個datanode上某個文件塊的讀取qps, 所以,從這些方面來排查,首先分析哪些表是關鍵表,對關鍵表看看是否都是大文件,如果是的話調整其為小文件,常見方式有repatition 輸出或者hive的reduce數。
經過多次測試,-這個符號不起作用
spark.sql(sql).withColumn("rn", row_number().over(Window.partitionBy('f_trans_id).orderBy(-'f_modify_time))) // 替代方案(最好用sql形式而不是DSL,感覺不是很直觀) spark.sql(sql).withColumn("rn", row_number().over(Window.partitionBy('f_trans_id).orderBy($"f_modify_time".desc)) spark.sql(sql).withColumn("rn", row_number().over(Window.partitionBy('f_trans_id).orderBy(col(f_modify_time).desc))
alter table
要加CASCADE
,否則回溯的歷史數據分區的數據在hive中看不到,原理是不加cascade
只對加了字段以后的元數據有用,對于舊分區回溯,即使數據回溯完成,你也是拿不到的,如果在回溯完才發現這個問題,可以change colunmn
的方式來補元數據
到此,相信大家對“Hive與Spark開發生產中遇到的問題有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。