1. 程式人生 > 其它 >hive面試題總結

hive面試題總結

hive面試題總結

1、hive的架構

1)使用者介面:Client CLI(command-line interface)、JDBC/ODBC(jdbc 訪問 hive)、WEBUI(瀏覽器訪問 hive) 2)元資料:Metastore 元資料包括:表名、表所屬的資料庫(預設是 default)、表的擁有者、列/分割槽欄位、 表的型別(是否是外部表)、表的資料所在目錄等; 預設儲存在自帶的 derby 資料庫中,推薦使用 MySQL 儲存 Metastore 3)Hadoop 使用 HDFS 進行儲存,使用 MapReduce 進行計算。 4)驅動器:Driver (1)解析器(SQL Parser):將 SQL 字串轉換成抽象語法樹 AST,這一步一般都用第三方工具庫完成,比如 antlr;對 AST 進行語法分析,比如表是否存在、欄位是否存在、SQL語義是否有誤。 (2)編譯器(Physical Plan):將 AST 編譯生成邏輯執行計劃。 (3)優化器(Query Optimizer):對邏輯執行計劃進行優化。 (4)執行器(Execution):把邏輯執行計劃轉換成可以執行的物理計劃。對於 Hive 來說,就是 MR/Spark。

2、hive和資料庫比較

Hive和資料庫除了擁有類似的查詢語言,再無類似之處。 1)資料儲存位置 Hive儲存在HDFS。資料庫將資料儲存在塊裝置或者本地檔案系統中。 2)資料更新 Hive中不建議對資料的改寫。而資料庫中的資料通常是需要經常進行修改的, 3)執行延遲 Hive執行延遲較高。資料庫的執行延遲較低。當然,這個是有條件的,即資料規模較小,當資料規模大到超過資料庫的處理能力的時候,Hive的平行計算顯然能體現出優勢。 4)資料規模 Hive支援很大規模的資料計算;資料庫可以支援的資料規模較小。

3、內部表和外部表

元資料、原始資料 1)刪除資料時: 內部表:元資料、原始資料,全刪除 外部表:元資料 只刪除 2)在公司生產環境下,什麼時候建立內部表,什麼時候建立外部表? 在公司中絕大多數場景都是外部表。 自己使用的臨時表,才會建立內部表;

4、4個by的區別

1)Order By:全域性排序,只有一個Reducer; 2)SortBy:分割槽內有序; 3)Distrbute By:類似MR中Partition,進行分割槽,結合sort by使用。 4)Cluster By:當Distribute by和Sorts by欄位相同時,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外還兼具Sort by的功能。但是排序只能是升序排序,不能指定排序規則為ASC或者DESC。 在生產環境中Order By用的比較少,容易導致OOM。 在生產環境中SortBy+ Distrbute By用的多。

5、系統函式

1)date_add、date_sub函式(加減日期) 2)next_day函式(周指標相關) 3)date_format函式(根據格式整理日期) 4)last_day函式(求當月最後一天日期) 5)collect_set函式 6)get_json_object解析json函式 7)NVL(表示式1,表示式2) 如果表示式1為空值,NVL返回值為表示式2的值,否則返回表示式1的值。

6、自定義UDF和UDTF函式

1)在專案中是否自定義過UDF、UDTF函式,以及用他們處理了什麼問題,及自定義步驟? (1)用UDF函式解析公共欄位;用UDTF函式解析事件欄位。 (2)自定義UDF:繼承UDF,重寫evaluate方法 (3)自定義UDTF:繼承自GenericUDTF,重寫3個方法:initialize(自定義輸出的列名和型別),process(將結果返回forward(result)),close 2)為什麼要自定義UDF/UDTF? 因為自定義函式,可以自己埋點Log列印日誌,出錯或者資料異常,方便除錯。

7、視窗函式

1)Rank (1)RANK() 排序相同時會重複,總數不會變 (2)DENSE_RANK() 排序相同時會重複,總數會減少 (3)ROW_NUMBER() 會根據順序計算 2)OVER():指定分析函式工作的資料視窗大小,這個資料視窗大小可能會隨著行的變而變化 (1)CURRENT ROW:當前行 (2)nPRECEDING:往前n行資料 (3)nFOLLOWING:往後n行資料 (4)UNBOUNDED:起點,UNBOUNDED PRECEDING表示從前面的起點, UNBOUNDEDFOLLOWING表示到後面的終點 (5)LAG(col,n):往前第n行資料 (6)LEAD(col,n):往後第n行資料 (7)NTILE(n):把有序分割槽中的行分發到指定資料的組中,各個組有編號,編號從1開始,對於每一行,NTILE返回此行所屬的組的編號。注意:n必須為int型別。 3)手寫TopN

8、hive優化

1)MapJoin 如果不指定MapJoin或者不符合MapJoin的條件,那麼Hive解析器會將Join操作轉換成Common Join,即:在Reduce階段完成join。容易發生資料傾斜。可以用MapJoin把小表全部載入到記憶體在map端進行join,避免reducer處理。 2)行列過濾 列處理:在SELECT中,只拿需要的列,如果有,儘量使用分割槽過濾,少用SELECT *。 行處理:在分割槽剪裁中,當使用外關聯時,如果將副表的過濾條件寫在Where後面,那麼就會先全表關聯,之後再過濾。 3)列式儲存 4)採用分割槽技術 5)合理設定Map數 mapred.min.split.size: 指的是資料的最小分割單元大小;min的預設值是1B mapred.max.split.size: 指的是資料的最大分割單元大小;max的預設值是256MB 通過調整max可以起到調整map數的作用,減小max可以增加map數,增大max可以減少map數。 需要提醒的是,直接調整mapred.map.tasks這個引數是沒有效果的。 https://www.cnblogs.com/swordfall/p/11037539.html 6)合理設定Reduce數 Reduce個數並不是越多越好 (1)過多的啟動和初始化Reduce也會消耗時間和資源; (2)另外,有多少個Reduce,就會有多少個輸出檔案,如果生成了很多個小檔案,那麼如果這些小檔案作為下一個任務的輸入,則也會出現小檔案過多的問題; 在設定Reduce個數的時候也需要考慮這兩個原則:處理大資料量利用合適的Reduce數;使單個Reduce任務處理資料量大小要合適; 7)小檔案如何產生的? (1)動態分割槽插入資料,產生大量的小檔案,從而導致map數量劇增; (2)reduce數量越多,小檔案也越多(reduce的個數和輸出檔案是對應的); (3)資料來源本身就包含大量的小檔案。 8)小檔案解決方案 (1)在Map執行前合併小檔案,減少Map數:CombineHiveInputFormat具有對小檔案進行合併的功能(系統預設的格式)。HiveInputFormat沒有對小檔案合併功能。 (2)merge // 輸出合併小檔案
SET hive.merge.mapfiles = true; -- 預設true,在map-only任務結束時合併小檔案
SET hive.merge.mapredfiles = true; -- 預設false,在map-reduce任務結束時合併小檔案
SET hive.merge.size.per.task = 268435456; -- 預設256M
SET hive.merge.smallfiles.avgsize = 16777216; -- 當輸出檔案的平均大小小於16m該值時,啟動一個獨立的map-reduce任務進行檔案merge
(3)開啟JVM重用
set mapreduce.job.jvm.numtasks=10
9)開啟map端combiner(不影響最終業務邏輯)
set hive.map.aggr=true;
10)壓縮(選擇快的) 設定map端輸出、中間結果壓縮。(不完全是解決資料傾斜的問題,但是減少了IO讀寫和網路傳輸,能提高很多效率)
set hive.exec.compress.intermediate=true --啟用中間資料壓縮
set mapreduce.map.output.compress=true --啟用最終資料壓縮
set mapreduce.map.outout.compress.codec=…; --設定壓縮方式
11)採用tez引擎或者spark引擎

9、hive解決資料傾斜方法

1)資料傾斜長啥樣? 資料分佈不均 2)怎麼產生的資料傾斜? (1)不同資料型別關聯產生資料傾斜 情形:比如使用者表中user_id欄位為int,log表中user_id欄位既有string型別也有int型別。當按照user_id進行兩個表的Join操作時。 後果:處理此特殊值的reduce耗時;只有一個reduce任務。預設的Hash操作會按int型的id來進行分配,這樣會導致所有string型別id的記錄都分配到一個Reducer中。 解決方式:把數字型別轉換成字串型別 select * from users a left outer join logs b on a.usr_id = cast(b.user_id as string) (2)控制空值分佈 在生產環境經常會用大量空值資料進入到一個reduce中去,導致資料傾斜。 解決辦法: 自定義分割槽,將為空的key轉變為字串加隨機數或純隨機數,將因空值而造成傾斜的資料分不到多個Reducer。 注意:對於異常值如果不需要的話,最好是提前在where條件裡過濾掉,這樣可以使計算量大大減少 3)解決資料傾斜的方法? (1)group by 注:group by 優於distinct group 解決方式:採用sum() group by的方式來替換count(distinct)完成計算。 (2)mapjoin (3)開啟資料傾斜時負載均衡 set hive.groupby.skewindata=true; 思想:就是先隨機分發並處理,再按照key group by來分發處理。 操作:當選項設定為true,生成的查詢計劃會有兩個MRJob。 第一個MRJob中,Map的輸出結果集合會隨機分佈到Reduce中,每個Reduce做部分聚合操作,並輸出結果,這樣處理的結果是相同的GroupBy Key有可能被分發到不同的Reduce中,從而達到負載均衡的目的; 第二個MRJob再根據預處理的資料結果按照GroupBy Key分佈到Reduce中(這個過程可以保證相同的原始GroupBy Key被分佈到同一個Reduce中),最後完成最終的聚合操作。 點評:它使計算變成了兩個mapreduce,先在第一個中在shuffle過程partition時隨機給 key打標記,使每個key隨機均勻分佈到各個reduce上計算,但是這樣只能完成部分計算,因為相同key沒有分配到相同reduce上。 所以需要第二次的mapreduce,這次就回歸正常shuffle,但是資料分佈不均勻的問題在第一次mapreduce已經有了很大的改善,因此基本解決資料傾斜。因為大量計算已經在第一次mr中隨機分佈到各個節點完成。

10、Hive裡邊欄位的分隔符用的什麼?為什麼用\t?有遇到過欄位裡邊有\t的情況嗎,怎麼處理的?

hive 預設的欄位分隔符為ascii碼的控制符\001(^A),建表的時候用fields terminated by '\001'。注意:如果採用\t或者\001等為分隔符,需要要求前端埋點和javaEE後臺傳遞過來的資料必須不能出現該分隔符,通過程式碼規範約束。一旦傳輸過來的資料含有分隔符,需要在前一級資料中轉義或者替換(ETL)。

11、Tez引擎優點?

Tez可以將多個有依賴的作業轉換為一個作業,這樣只需寫一次HDFS,且中間節點較少,從而大大提升作業的計算效能。 Mr/tez/spark區別: Mr引擎:多job串聯,基於磁碟,落盤的地方比較多。雖然慢,但一定能跑出結果。一般處理,周、月、年指標。 Spark引擎:雖然在Shuffle過程中也落盤,但是並不是所有運算元都需要Shuffle,尤其是多運算元過程,中間過程不落盤 DAG有向無環圖。 兼顧了可靠性和效率。一般處理天指標。 Tez引擎:完全基於記憶體。 注意:如果資料量特別大,慎重使用。容易OOM。一般用於快速出結果,資料量比較小的場景。

12、MySQL元資料備份

(1)元資料備份(重點,如資料損壞,可能整個叢集無法執行,至少要保證每日零點之後備份到其它伺服器兩個複本) 2)MySQLutf8超過位元組數問題 MySQL的utf8編碼最多儲存3個位元組,當資料中存在表情號、特色符號時會佔用超過3個位元組數的位元組,那麼會出現錯誤 Incorrect string value: '\xF0\x9F\x91\x91\xE5\xB0...' 解決辦法:將utf8修改為utf8mb4 首先修改庫的基字符集和資料庫排序規則

再使用 SHOW VARIABLES LIKE '%char%'; 命令檢視引數

確保這幾個引數的value值為utf8mb4 如果不是使用set命令修改 如:set character_set_server = utf8mb4;

13、Union與Union all區別

1)union會將聯合的結果集去重,效率較union all差 2)union all不會對結果集去重,所以效率高