大數據面試題——Hive篇

1. Hive有哪些方式保存元數據,各有什麼特點?

Hive支持三種不同的元存儲服務器,分別爲:內嵌式元存儲服務器、本地元存儲服務器、遠程元存儲服務器,每種存儲方式使用不同的配置參數。

  • 內嵌式元存儲主要用於單元測試,在該模式下每次只有一個進程可以連接到元存儲,Derby是內嵌式元存儲的默認數據庫
  • 在本地模式下,每個Hive客戶端都會打開到數據存儲的連接並在該連接上請求SQL查詢。
  • 在遠程模式下,所有的Hive客戶端都將打開一個到元數據服務器的連接,該服務器依次查詢元數據,元數據服務器和客戶端之間使用Thrift協議通信。

2. 請說明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 的功能。

3. 簡要描述數據庫中的 null,說出null在hive底層如何存儲,並解釋select a.* from t1 a left outer join t2 b on a.id=b.id where b.id is not null; 語句的含義?

null與任何值運算的結果都是null, 可以使用is null、is not null函數指定在其值爲null情況下的取值。
null在hive底層默認是用’\N’來存儲的,可以通過alter table test SET SERDEPROPERTIES(‘serialization.null.format’ = ‘a’);來修改。
該語句的含義是查詢出t1表中與t2表中id相等的所有信息。

4. Hive優化(重要)

4.1 Fetch抓取

Fetch抓取是指,Hive中對某些情況的查詢可以不必使用MapReduce計算。例如:SELECT * FROM employees;在這種情況下,Hive可以簡單地讀取employee對應的存儲目錄下的文件,然後輸出查詢結果到控制檯。
在hive-default.xml.template文件中hive.fetch.task.conversion默認是more,老版本hive默認是minimal,該屬性修改爲more以後,在全局查找、字段查找、limit查找等都不走mapreduce。

將hive.fetch.task.conversion設置成more,然後執行查詢語句,如一下查詢方式都不會執行MR程序。

hive (default)> set hive.fetch.task.conversion=more;
hive (default)> select * from emp;
hive (default)> select ename from emp;
hive (default)> select ename from emp limit 3;

4.2 大小表Join

將key相對分散,並且數據量小的表放在join的左邊,這樣可以有效減少內存溢出錯誤發生的機率;再進一步,可以使用Group讓小的維度表(1000條以下的記錄條數)先進內存。在map端完成reduce。

4.3 Map Join

這一部分 南國之前的博客中曾經寫過一篇博客Hadoop中Join多種應用,這裏再做下簡單敘述。

如果不指定MapJoin或者不符合MapJoin的條件,那麼Hive解析器會將Join操作轉換成Common Join,即:在Reduce階段完成join。容易發生數據傾斜。可以用MapJoin把小表全部加載到內存在map端進行join,避免reducer處理。
1)開啓MapJoin參數設置:
(1)設置自動選擇Mapjoin
set hive.auto.convert.join = true; 默認爲true
(2)大表小表的閥值設置(默認25M以下認爲是小表):
set hive.mapjoin.smalltable.filesize=25000000;
2)MapJoin工作機制
在這裏插入圖片描述
具體過程:

  • 首先是Task A,它是一個Local Task(在客戶端本地執行的Task),負責掃描小表b的數據,將其轉換成一個HashTable的數據結構,並寫入本地的文件中,之後將該文件加載到DistributeCache中。
  • 接下來是Task B,該任務是一個沒有Reduce的MR,啓動MapTasks掃描大表a,在Map階段,根據a的每一條記錄去和DistributeCache中b表對應的HashTable關聯,並直接輸出結果。
  • 由於MapJoin沒有Reduce,所以由Map直接輸出結果文件,有多少個Map Task,就有多少個結果文件。

案例:
(1)開啓Mapjoin功能
set hive.auto.convert.join = true; 默認爲true
(2)執行小表JOIN大表語句

insert overwrite table jointable
select b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from smalltable s join bigtable  b on s.id = b.id;

Time taken: 24.594 seconds
(3)執行大表JOIN小表語句

insert overwrite table jointable
select b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from bigtable  b
join smalltable  s on s.id = b.id;

Time taken: 24.315 seconds

4.4 Group By

默認情況下,Map階段同一Key數據分發給一個reduce,當一個key數據過大時就傾斜了。
並不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端進行部分聚合,最後在Reduce端得出最終結果。
開啓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中),最後完成最終的聚合操作。

4.5 Count(Distinct) 去重統計優化

數據量小的時候不需要優化處理,但是當數據量特別大的時候,由於COUNT DISTINCT操作需要用一個Reduce Task來完成,這一個Reduce需要處理的數據量太大,就會導致整個Job很難完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替換。

4.6 行列過濾

列處理:在SELECT中,只拿需要的列,如果有,儘量使用分區過濾,少用SELECT *。
行處理:在分區剪裁中,當使用外關聯時,如果將副表的過濾條件寫在Where後面,那麼就會先全表關聯,之後再過濾,比如:
案例實操:
(1)測試先關聯兩張表,再用where條件過濾

hive (default)> select o.id from bigtable b
				join ori o on o.id = b.id
				where o.id <= 10;

(2)通過子查詢後,再關聯表

hive (default)> select b.id from bigtable b
				join (select id from ori where id <= 10 ) o on b.id = o.id;

4.7 並行執行

Hive會將一個查詢轉化成一個或者多個階段。這樣的階段可以是MapReduce階段、抽樣階段、合併階段、limit階段。或者Hive執行過程中可能需要的其他階段。默認情況下,Hive一次只會執行一個階段。不過,某個特定的job可能包含衆多的階段,而這些階段可能並非完全互相依賴的,也就是說有些階段是可以並行執行的,這樣可能使得整個job的執行時間縮短。不過,如果有更多的階段可以並行執行,那麼job可能就越快完成。
通過設置參數hive.exec.parallel值爲true,就可以開啓併發執行。不過,在共享集羣中,需要注意下,如果job中並行階段增多,那麼集羣利用率就會增加。

set hive.exec.parallel=true;              //打開任務並行執行
set hive.exec.parallel.thread.number=16;  //同一個sql允許最大並行度,默認爲8。

4.8 嚴格模式strict

Hive提供了一個嚴格模式,可以防止用戶執行那些可能意向不到的不好的影響的查詢。
通過設置屬性hive.mapred.mode值爲默認是非嚴格模式nonstrict 。開啓嚴格模式需要修改hive.mapred.mode值爲strict,開啓嚴格模式可以禁止3種類型的查詢。
1)對於分區表,除非where語句中含有分區字段過濾條件來限制範圍,否則不允許執行。換句話說,就是用戶不允許掃描所有分區。進行這個限制的原因是,通常分區表都擁有非常大的數據集,而且數據增加迅速。沒有進行分區限制的查詢可能會消耗令人不可接受的巨大資源來處理這個表。
2)對於使用了order by語句的查詢,要求必須使用limit語句。因爲order by爲了執行排序過程會將所有的結果數據分發到同一個Reducer中進行處理,強制要求用戶增加這個LIMIT語句可以防止Reducer額外執行很長一段時間。
3)限制笛卡爾積的查詢。對關係型數據庫非常瞭解的用戶可能期望在執行JOIN查詢的時候不使用ON語句而是使用where語句,這樣關係數據庫的執行優化器就可以高效地將WHERE語句轉化成那個ON語句。不幸的是,Hive並不會執行這種優化,因此,如果表足夠大,那麼這個查詢就會出現不可控的情況。

4.9 JVM重用

JVM重用是Hadoop調優參數的內容,其對Hive的性能具有非常大的影響,特別是對於很難避免小文件的場景或task特別多的場景,這類場景大多數執行時間都很短。

Hadoop的默認配置通常是使用派生JVM來執行map和Reduce任務的。這時JVM的啓動過程可能會造成相當大的開銷,尤其是執行的job包含有成百上千task任務的情況。JVM重用可以使得JVM實例在同一個job中重新使用N次。N的值可以在Hadoop的mapred-site.xml文件中進行配置。通常在10-20之間,具體多少需要根據具體業務場景測試得出。

<property>
  <name>mapreduce.job.jvm.numtasks</name>
  <value>10</value>
  <description>How many tasks to run per jvm. If set to -1, there is
  no limit. 
  </description>
</property>

這個功能的缺點是,開啓JVM重用將一直佔用使用到的task插槽,以便進行重用,直到任務完成後才能釋放。如果某個“不平衡的”job中有某幾個reduce task執行的時間要比其他Reduce task消耗的時間多的多的話,那麼保留的插槽就會一直空閒着卻無法被其他的job使用,直到所有的task都結束了纔會釋放。

4.9 Explain(執行計劃)

1)基本語法
EXPLAIN [EXTENDED | DEPENDENCY | AUTHORIZATION] query
2)案例實操
(1)查看下面這條語句的執行計劃
hive (default)> explain select * from emp;
hive (default)> explain select deptno, avg(sal) avg_sal from emp group by deptno;
(2)查看詳細執行計劃
hive (default)> explain extended select * from emp;
hive (default)> explain extended select deptno, avg(sal) avg_sal from emp group by deptno;

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