Hive面試題整理(一)
1、Hive表關聯查詢,如何解決數據傾斜的問題?(☆☆☆☆☆)
1)傾斜原因:map輸出數據按key Hash的分配到reduce中,由於key分布不均勻、業務數據本身的特、建表時考慮不周、等原因造成的reduce 上的數據量差異過大。
(1)key分布不均勻;
(2)業務數據本身的特性;
(3)建表時考慮不周;
(4)某些SQL語句本身就有數據傾斜;
如何避免:對於key為空產生的數據傾斜,可以對其賦予一個隨機值。
2)解決方案
(1)參數調節:
hive.map.aggr = true
hive.groupby.skewindata=true
有數據傾斜的時候進行負載均衡,當選項設定位true,生成的查詢計划會有兩個MR Job。第一個MR Job中,Map的輸出結果集合會隨機分布到Reduce中,每個Reduce做部分聚合操作,並輸出結果,這樣處理的結果是相同的Group By Key有可能被分發到不同的Reduce中,從而達到負載均衡的目的;第二個MR Job再根據預處理的數據結果按照Group By Key 分布到 Reduce 中(這個過程可以保證相同的 Group By Key 被分布到同一個Reduce中),最后完成最終的聚合操作。
(2)SQL 語句調節:
① 選用join key分布最均勻的表作為驅動表。做好列裁剪和filter操作,以達到兩表做join 的時候,數據量相對變小的效果。
② 大小表Join:
使用map join讓小的維度表(1000 條以下的記錄條數)先進內存。在map端完成reduce。
③ 大表Join大表:
把空值的key變成一個字符串加上隨機數,把傾斜的數據分到不同的reduce上,由於null 值關聯不上,處理后並不影響最終結果。
④ count distinct大量相同特殊值:
count distinct 時,將值為空的情況單獨處理,如果是計算count distinct,可以不用處理,直接過濾,在最后結果中加1。如果還有其他計算,需要進行group by,可以先將值為空的記錄單獨處理,再和其他計算結果進行union。
2、Hive的HSQL轉換為MapReduce的過程?(☆☆☆☆☆)
HiveSQL ->AST(抽象語法樹) -> QB(查詢塊) ->OperatorTree(操作樹)->優化后的操作樹->mapreduce任務樹->優化后的mapreduce任務樹
過程描述如下:
SQL Parser:Antlr定義SQL的語法規則,完成SQL詞法,語法解析,將SQL轉化為抽象語法樹AST Tree;
Semantic Analyzer:遍歷AST Tree,抽象出查詢的基本組成單元QueryBlock;
Logical plan:遍歷QueryBlock,翻譯為執行操作樹OperatorTree;
Logical plan optimizer: 邏輯層優化器進行OperatorTree變換,合並不必要的ReduceSinkOperator,減少shuffle數據量;
Physical plan:遍歷OperatorTree,翻譯為MapReduce任務;
Logical plan optimizer:物理層優化器進行MapReduce任務的變換,生成最終的執行計划。
3、Hive底層與數據庫交互原理?(☆☆☆☆☆)
由於Hive的元數據可能要面臨不斷地更新、修改和讀取操作,所以它顯然不適合使用Hadoop文件系統進行存儲。目前Hive將元數據存儲在RDBMS中,比如存儲在MySQL、Derby中。元數據信息包括:存在的表、表的列、權限和更多的其他信息。
4、Hive的兩張表關聯,使用MapReduce怎么實現?(☆☆☆☆☆)
如果其中有一張表為小表,直接使用map端join的方式(map端加載小表)進行聚合。
如果兩張都是大表,那么采用聯合key,聯合key的第一個組成部分是join on中的公共字段,第二部分是一個flag,0代表表A,1代表表B,由此讓Reduce區分客戶信息和訂單信息;在Mapper中同時處理兩張表的信息,將join on公共字段相同的數據划分到同一個分區中,進而傳遞到一個Reduce中,然后在Reduce中實現聚合。
5、請談一下Hive的特點,Hive和RDBMS有什么異同?
hive是基於Hadoop的一個數據倉庫工具,可以將結構化的數據文件映射為一張數據庫表,並提供完整的sql查詢功能,可以將sql語句轉換為MapReduce任務進行運行。其優點是學習成本低,可以通過類SQL語句快速實現簡單的MapReduce統計,不必開發專門的MapReduce應用,十分適合數據倉庫的統計分析,但是Hive不支持實時查詢。
Hive與關系型數據庫的區別:
6、請說明hive中 Sort By,Order By,Cluster By,Distrbute By各代表什么意思?
order by:會對輸入做全局排序,因此只有一個reducer(多個reducer無法保證全局有序)。只有一個reducer,會導致當輸入規模較大時,需要較長的計算時間。
sort by:不是全局排序,其在數據進入reducer前完成排序。
distribute by:按照指定的字段對數據進行划分輸出到不同的reduce中。
cluster by:除了具有 distribute by 的功能外還兼具 sort by 的功能。
7、寫出hive中split、coalesce及collect_list函數的用法(可舉例)?
split將字符串轉化為數組,即:split(‘a,b,c,d’ , ‘,’) ==> [“a”,“b”,“c”,“d”]。
coalesce(T v1, T v2, …) 返回參數中的第一個非空值;如果所有值都為 NULL,那么返回NULL。
collect_list列出該字段所有的值,不去重 => select collect_list(id) from table。
8、Hive有哪些方式保存元數據,各有哪些特點?
Hive支持三種不同的元存儲服務器,分別為:內嵌式元存儲服務器、本地元存儲服務器、遠程元存儲服務器,每種存儲方式使用不同的配置參數。
內嵌式元存儲主要用於單元測試,在該模式下每次只有一個進程可以連接到元存儲,Derby是內嵌式元存儲的默認數據庫。
在本地模式下,每個Hive客戶端都會打開到數據存儲的連接並在該連接上請求SQL查詢。
在遠程模式下,所有的Hive客戶端都將打開一個到元數據服務器的連接,該服務器依次查詢元數據,元數據服務器和客戶端之間使用Thrift協議通信。
11、所有的Hive任務都會有MapReduce的執行嗎?
不是,從Hive0.10.0版本開始,對於簡單的不需要聚合的類似SELECT from
LIMIT n語句,不需要起MapReduce job,直接通過Fetch task獲取數據。
12、Hive的函數:UDF、UDAF、UDTF的區別?
UDF:單行進入,單行輸出
UDAF:多行進入,單行輸出
UDTF:單行輸入,多行輸出
13、說說對Hive桶表的理解?
桶表是對數據進行哈希取值,然后放到不同文件中存儲。
數據加載到桶表時,會對字段取hash值,然后與桶的數量取模。把數據放到對應的文件中。物理上,每個桶就是表(或分區)目錄里的一個文件,一個作業產生的桶(輸出文件)和reduce任務個數相同。
桶表專門用於抽樣查詢,是很專業性的,不是日常用來存儲數據的表,需要抽樣查詢時,才創建和使用桶表。
Hive面試題整理(二)
1、Fetch抓取
Fetch抓取是指,Hive中對某些情況的查詢可以不必使用MapReduce計算。例如:SELECT * FROM employees;在這種情況下,Hive可以簡單地讀取employee對應的存儲目錄下的文件,然后輸出查詢結果到控制台。
在hive-default.xml.template文件中hive.fetch.task.conversion默認是more,老版本hive默認是minimal,該屬性修改為more以后,在全局查找、字段查找、limit查找等都不走mapreduce。
2、本地模式
大多數的Hadoop Job是需要Hadoop提供的完整的可擴展性來處理大數據集的。不過,有時Hive的輸入數據量是非常小的。在這種情況下,為查詢觸發執行任務時消耗可能會比實際job的執行時間要多的多。對於大多數這種情況,Hive可以通過本地模式在單台機器上處理所有的任務。對於小數據集,執行時間可以明顯被縮短。
用戶可以通過設置hive.exec.mode.local.auto的值為true,來讓Hive在適當的時候自動啟動這個優化。
表的優化
3、小表、大表Join
將key相對分散,並且數據量小的表放在join的左邊,這樣可以有效減少內存溢出錯誤發生的幾率;再進一步,可以使用Group讓小的維度表(1000條以下的記錄條數)先進內存。在map端完成reduce。
實際測試發現:新版的hive已經對小表JOIN大表和大表JOIN小表進行了優化。小表放在左邊和右邊已經沒有明顯區別。
4、大表Join大表
1)空KEY過濾
有時join超時是因為某些key對應的數據太多,而相同key對應的數據都會發送到相同的reducer上,從而導致內存不夠。此時我們應該仔細分析這些異常的key,很多情況下,這些key對應的數據是異常數據,我們需要在SQL語句中進行過濾。例如key對應的字段為空。
2)空key轉換
有時雖然某個key為空對應的數據很多,但是相應的數據不是異常數據,必須要包含在join的結果中,此時我們可以表a中key為空的字段賦一個隨機的值,使得數據隨機均勻地分不到不同的reducer上。
5、Group By
默認情況下,Map階段同一Key數據分發給一個reduce,當一個key數據過大時就傾斜了。
並不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端進行部分聚合,最后在Reduce端得出最終結果。
1)開啟Map端聚合參數設置
(1)是否在Map端進行聚合,默認為True
hive.map.aggr = true
(2)在Map端進行聚合操作的條目數目
hive.groupby.mapaggr.checkinterval = 100000
(3)有數據傾斜的時候進行負載均衡(默認是false)
hive.groupby.skewindata = true
當選項設定為 true,生成的查詢計划會有兩個MR Job。第一個MR Job中,Map的輸出結果會隨機分布到Reduce中,每個Reduce做部分聚合操作,並輸出結果,這樣處理的結果是相同的Group By Key有可能被分發到不同的Reduce中,從而達到負載均衡的目的;第二個MR Job再根據預處理的數據結果按照Group By Key分布到Reduce中(這個過程可以保證相同的Group By Key被分布到同一個Reduce中),最后完成最終的聚合操作。
6、Count(Distinct) 去重統計
數據量小的時候無所謂,數據量大的情況下,由於COUNT DISTINCT操作需要用一個Reduce Task來完成,這一個Reduce需要處理的數據量太大,就會導致整個Job很難完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替換
7、笛卡爾積
盡量避免笛卡爾積,join的時候不加on條件,或者無效的on條件,Hive只能使用1個reducer來完成笛卡爾積
8、行列過濾
列處理:在SELECT中,只拿需要的列,如果有,盡量使用分區過濾,少用SELECT *。
行處理:在分區剪裁中,當使用外關聯時,如果將副表的過濾條件寫在Where后面,那么就會先全表關聯,之后再過濾。
數據傾斜
9、 Map數
1)通常情況下,作業會通過input的目錄產生一個或者多個map任務。
主要的決定因素有:input的文件總個數,input的文件大小,集群設置的文件塊大小。
2)是不是map數越多越好?
答案是否定的。如果一個任務有很多小文件(遠遠小於塊大小128m),則每個小文件也會被當做一個塊,用一個map任務來完成,而一個map任務啟動和初始化的時間遠遠大於邏輯處理的時間,就會造成很大的資源浪費。而且,同時可執行的map數是受限的。
3)是不是保證每個map處理接近128m的文件塊,就高枕無憂了?
答案也是不一定。比如有一個127m的文件,正常會用一個map去完成,但這個文件只有一個或者兩個小字段,卻有幾千萬的記錄,如果map處理的邏輯比較復雜,用一個map任務去做,肯定也比較耗時。
針對上面的問題2和3,我們需要采取兩種方式來解決:即減少map數和增加map數;
10、小文件進行合並
在map執行前合並小文件,減少map數:CombineHiveInputFormat具有對小文件進行合並的功能(系統默認的格式)。HiveInputFormat沒有對小文件合並功能。
set hive.input.format= org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
11、復雜文件增加Map數
當input的文件都很大,任務邏輯復雜,map執行非常慢的時候,可以考慮增加Map數,來使得每個map處理的數據量減少,從而提高任務的執行效率。
增加map的方法為:根據computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M公式,調整maxSize最大值。讓maxSize最大值低於blocksize就可以增加map的個數。
12、Reduce數
1)調整reduce個數方法一
(1)每個Reduce處理的數據量默認是256MB
hive.exec.reducers.bytes.per.reducer=256000000
(2)每個任務最大的reduce數,默認為1009
hive.exec.reducers.max=1009
(3)計算reducer數的公式
N=min(參數2,總輸入數據量/參數1)
2)調整reduce個數方法二
在hadoop的mapred-default.xml文件中修改
設置每個job的Reduce個數
set mapreduce.job.reduces = 15;
3)reduce個數並不是越多越好
(1)過多的啟動和初始化reduce也會消耗時間和資源;
(2)另外,有多少個reduce,就會有多少個輸出文件,如果生成了很多個小文件,那么如果這些小文件作為下一個任務的輸入,則也會出現小文件過多的問題;
在設置reduce個數的時候也需要考慮這兩個原則:處理大數據量利用合適的reduce數;使單個reduce任務處理數據量大小要合適。
**==========================**
13、並行執行
Hive會將一個查詢轉化成一個或者多個階段。這樣的階段可以是MapReduce階段、抽樣階段、合並階段、limit階段。或者Hive執行過程中可能需要的其他階段。默認情況下,Hive一次只會執行一個階段。不過,某個特定的job可能包含眾多的階段,而這些階段可能並非完全互相依賴的,也就是說有些階段是可以並行執行的,這樣可能使得整個job的執行時間縮短。不過,如果有更多的階段可以並行執行,那么job可能就越快完成。
通過設置參數hive.exec.parallel值為true,就可以開啟並發執行。不過,在共享集群中,需要注意下,如果job中並行階段增多,那么集群利用率就會增加。