Hive之面試集錦<二>

Hive之面試集錦<二>

函數

Hive函數的考察主要是函數的使用,一般代碼類的題目居多,窗口函數是考察的要點。

18.統計每天的人均播放次數和播放時長,其中播放次數按照起播日誌來算,播放時長按照播放結束日誌來統計

SELECT a.key_day,a.avg_play_num,b.avg_duration
(
select key_day,count(device_id)/count(distinct device_id) as avg_play_num
from test.video_play
where event = 'start' //限定為起播日誌
group by key_day
) a
join
(
select key_day,sum(duration)/count(distinct device_id) as avg_duration
from test.video_play
where event = 'end' //限定為結束播放日誌
group by key_day
) b
on a.key_day = b.key_day

19.找出每天播放時長最長的用戶

select key_day,device_id,sum_duration
from
(select key_day,device_id,sum(play_duration) as sum_duration,rank() over (partition by key_day order by sum(play_duration) desc) as rank
from test.video_play
where event = 'end'
group by key_day,device_id
) a
where rank = 1

20.你知道哪些統計函數和窗口函數嗎?

  • 統計函數有:sum、avg、max/min、count
  • 窗口函數常用的有:除了上述統計函數外,還有first_value/last_value、lag/lead、rank、row_number

21.hive中 order by,sort by,cluster by,distrbute by,partition by各代表什麼意思?

  • order by:會對輸入做全局排序,因此只有一個reducer(多個reducer無法保證全局有序)。當輸入規模較大時,需要較長的計算時間。
  • sort by:不是全局排序,其在數據進入reducer前完成排序。
  • distribute by:按照指定的字段對數據進行劃分輸出到不同的reducer中。
  • cluster by:除了具有 distribute by 的功能外還兼具 sort by 的功能。
  • partition by
    :按照指定字段進行分區,用在窗口函數中。

數據傾斜

22.什麼是數據傾斜?

數據傾斜就是數據的分佈不平衡,某些地方特別多,某些地方又特別少,導致在處理數據的時候,有些很快就處理完了,而有些又遲遲未能處理完,導致整體任務最終遲遲無法完成,這種現象就是數據傾斜。

23.你知道發生數據傾斜的原因嗎?

發生數據傾斜的原因有很多,大致可以歸為:

1)key分佈不均勻;

2)數據本身的特性,原本按照日期進行分區,如果在特定日期數據量劇增,就有可能造成傾斜;

3)建表時考慮不周,分區設置不合理或者過少;

4)某些 HQL 語句本身就容易產生數據傾斜,如 join。

24.哪些HQL操作可能會發生數據傾斜?

Hive之面試集錦<二>

對照上面的表格,可以得出有三種情況可能會發生數據傾斜:

1)join

大小表join的時候,其中一個較小表的key集中,這樣分發到某一個或者幾個的Reduce上的數據就可能遠高於平均值;

兩張大表join的時候,如果有很多0值和空值,那麼這些0值或者空值就會分到一個Reduce上進行處理;

join的時候,不同數據類型進行關聯,發生類型轉換的時候可能會產生null值,null值也會被分到一個Reduce上進行處理;

2)group by

進行分組的字段的值太少,造成Reduce的數量少,相應的每個Reduce的壓力就大;

3)count distinct

count distinct的時候相同的值會分配到同一個Reduce上,如果存在特殊的值太多也會造成數據傾斜。

Hive優化

Hive優化包括Hive Sql優化以及Hive的配置參數優化。

25.count(distinct uid),該用法在MR 的 reduce 階段只有一個 reduce 來處理,當數據量較大會導致嚴重的數據傾斜,如何進行優化呢?

可以先對uid進行去重,然後再count統計。

select count(1) from (select distinct(uid) d_uid from table) x

26.以下代碼,如果數據量很大,會有什麼問題?如何優化?

select uid,upload_time,event_type,record_data
from calendar_record_log
where day_p between '20190101' and '20190131'
order by upload_time desc,event_type desc;

Hive SQL中的order by就是將結果按某字段全局排序,這會導致所有map端數據都進入一個reducer中,在數據量大時可能會長時間計算不完。

可以使用sort by,會視情況啟動多個reducer進行排序,並且保證每個reducer內局部有序。為了控制map端數據分配到reducer的key,往往還要配合distribute by一同使用,如果不加distribute by的話,map端數據就會隨機分配到reducer。

下面是優化後的代碼。

select uid,upload_time,event_type,record_data
from calendar_record_log
where day_p between '20190101' and '20190131'

distribute by uid
sort by upload_time desc,event_type desc;

27.談談如何對join操作進行優化?

join優化是個複雜的問題,可以從以下幾點進行優化:

1)小表前置

大小表在join的時候,應該將小表放在前面,Hive在解析帶join的SQL語句時,會默認將最後一個表作為大表,將前面的表作為小表並試圖將它們讀進內存。如果表順序寫反,大表在前面,可能會引發OOM。

2)key值相同

多表join的時候儘量使用相同的key來關聯,這樣會將會將多個join合併為一個MR job來處理。

3)利用map join特性

map join特別適合大小表join的情況。Hive會將大表和小表在map端直接完成join過程,消滅reduce,效率很高。Hive 0.8版本之前,需要加上map join的暗示,以顯式啟用map join特性,具體做法是在select語句後面增加/*+mapjoin(需要廣播的較小表)*/。

map join的配置項是hive.auto.convert.join,默認值true;還可以控制map join啟用的條件,hive.mapjoin.smalltable.filesize,當較小表大小小於該值就會啟用map join,默認值25MB。

28.對於空值或者無意義的值引發的數據傾斜,該怎麼處理呢?

這在寫程序的時候要考慮清楚,這些異常值的過濾會不會影響計算結果,如果影響那就不能直接過濾掉,可以將這些異常的key用隨機方式打散,例如將用戶ID為null的記錄隨機改為負值。

29.如何調整mapper數?

mapper數量與輸入文件的split數息息相關,可以通過設置相關參數來調整mapper數。

1)可以直接通過參數mapred.map.tasks(默認值2)來設定mapper數的期望值,但它不一定是最終mapper數;

2)輸入文件的總大小為total_input_size。HDFS中,一個塊的大小由參數dfs.block.size指定,默認值64MB或128MB。所以得出來的默認mapper數就是:

default_mapper_num = total_input_size / dfs.block.size,但是它也不一定是最終的mapper數;

3)設置參數mapred.min.split.size(默認值1B)和mapred.max.split.size(默認值64MB)分別用來指定split的最小和最大值。那麼split大小和split數計算規則是:

split_size = MAX(mapred.min.split.size, MIN(mapred.max.split.size, dfs.block.size));

split_num = total_input_size / split_size。

4)最終得出mapper數:

mapper_num = MIN(split_num, MAX(default_mapper_num, mapred.map.tasks))。

其中可變的參數有:mapred.map.tasks、dfs.block.size(不會為了一個程序去修改,但是也算是一個可變參數)、mapred.min.split.size、mapred.max.split.size,通過調整他們來實現,mapper數的變化。

30.如何調整reducer數?

使用參數mapred.reduce.tasks可以直接設定reducer數量,不像mapper一樣是期望值。如果不設這個參數的話,Hive就會自行推測,邏輯如下:

1)參數hive.exec.reducers.bytes.per.reducer用來設定每個reducer能夠處理的最大數據量。

2)參數hive.exec.reducers.max用來設定每個job的最大reducer數量。

3)reducer數:

reducer_num = MIN(total_input_size / reducers.bytes.per.reducer, reducers.max)。

reducer數量決定了輸出文件的數量。如果reducer數太多,會產生大量小文件,對HDFS造成壓力。如果reducer數太少,每個reducer要處理很多數據,容易拖慢執行時間也有可能造成OOM。

31.什麼時候又需要合併文件?如何合併小文件?

當有很多小文件的時候沒需要合併小文件,可以在輸入階段合併,也可以在輸出階段合併。

1)輸入階段合併

要想文件自動合併,需要更改Hive的輸入文件格式,通過參數hive.input.format來更改,默認值是org.apache.hadoop.hive.ql.io.HiveInputFormat,需要改成org.apache.hadoop.hive.ql.io.CombineHiveInputFormat。還需要設置mapred.min.split.size.per.node和mapred.min.split.size.per.rack這兩個參數,他們的含義是單節點和單機架上的最小split大小。設置完後,如果發現有split大小小於這兩個值(默認都是100MB),則會進行合併。

2)輸出階段合併

設置hive.merge.mapfiles為true可以將map-only任務的輸出合併;

設置hive.merge.mapredfiles為true可以將map-reduce任務的輸出合併。另外,設置hive.merge.size.smallfiles.avgsize可以指定所有輸出文件大小的均值閾值,一旦低於這個閾值,就會啟動一個任務來進行合併。

32.什麼是嚴格模式?

嚴格模式不允許用戶執行3種有風險的HiveSQL語句,一旦執行就會直接失敗。這3種語句是:

1)查詢分區表時不限定分區列的語句;

2)兩表join產生了笛卡爾積的語句;

3)用order by來排序但沒有指定limit的語句。

將參數hive.mapred.mode設為strict則為開啟嚴格模式。


分享到:


相關文章: