1. 程式人生 > >Hive 企業級調優

Hive 企業級調優

1 Fetch 抓取

Fectch 抓取是指對某些情況下的查詢不必使用 MapReduce 計算

將 hive.fetch.task.conversion 設定成 more,在全域性查詢、欄位查詢、limit查詢等都不走 MapReduce

2 本地模式

多數的 Hadoop Job 是需要 Hadoop 提供的完整的可擴充套件性來處理大資料集的,不過,有時 Hive 的輸入資料量是非常小的,在這種情況下,為查詢觸發執行任務消耗的時間可能會比實際job的執行時間要多的多,對於大多數這種情況,Hive 可以通過本地模式在單臺機器上處理所有的任務,對於小資料集,執行時間可以明顯被縮短

將 hive.exec.mode.local.auto 設定成 true,讓 Hive 在適當的時候自動啟動這個優化

3 表優化

3.1 空 KEY 過濾

有時 JOIN 超時是因為某些 KEY 對應的資料太多,而相同 KEY 對應的資料都會發送到相同的 Reducer 上,從而導致記憶體不夠,此時我們應該仔細分很多情況下,這些 KEY 對應的資料是異常資料,我們需要在 SQL 語句中進行過濾。

3.2 空 KEY 轉換

有時雖然某個 KEY 為空對應的資料很多,但是相應的資料不是異常資料,必須要包含在 JOIN 的結果中,此時我們可以將表中 KEY 為空的欄位賦一個隨機的值,使得資料隨機均勻地分不到不同的 Reducer 上。

3.3 MapJOIN

如果不指定 MapJOIN 或者不符合 MapJOIN 的條件,那麼 Hive 解析器會將 JOIN 轉換成 Common JOIN,即:在Reduce階段完成 JOIN,容易發生資料傾斜,可以用 MapJOIN 把小表載入到記憶體在 Map 端進行 JOIN,避 Reducer 處理。

### 3.4 Group By

預設情況下,Map階段同一Key資料分發給一個reduce,當一個key資料過大時就傾斜了

# 是否在Map端進行聚合
set hive.map.aggr = true
# 在Map端進行聚合操作的條目數目
set hive.groupby.mapaggr.checkinterval = 100000
# 有資料傾斜的時候進行負載均衡
set 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 中),最後完成最終的聚合操作

3.5 Count(Distinct)

資料量小的時候無所謂,資料量大的情況下,由於 COUNT DISTINCT 的全聚合操作,即使設定了 Reduce Task 個數,Hive 也只會啟動一個Reduce,這就造成一個 Reduce 處理的資料量太大,導致整個 Job 很難完成,一般 COUNT DISTINCT 使用先 GROUP BY 再 COUNT 的方式替換

### 3.6 笛卡爾積

不使用笛卡爾積

### 3.7 行列過濾

禁止使用 SELECT *

3.8 動態分割槽調整

對分割槽表Insert資料時候,資料庫自動會根據分割槽欄位的值,將資料插入到相應的分割槽中,即動態分割槽

# 開啟動態分割槽功能
hive.exec.dynamic.partition=true
# 設定為非嚴格模式
hive.exec.dynamic.partition.mode=nonstrict
# 在所有執行MR的節點上,最大一共可以建立多少個動態分割槽,預設1000
hive.exec.max.dynamic.partitions=1000
# 在每個執行MR的節點上,最大可以建立多少個動態分割槽,該引數需要根據實際的資料來設定
hive.exec.max.dynamic.partitions.pernode=100
# 整個MR Job中,最大可以建立多少個HDFS檔案,預設100000
hive.exec.max.created.files=100000
# 當有空分割槽生成時,是否丟擲異常。一般不需要設定
hive.error.on.empty.partition=false

4 合理設定 MapReduce 數量

4.1 複雜檔案增加 Map 數

當 input 的檔案都很大,任務邏輯複雜,Map 執行非常慢的時候,可以考慮增加 Map 數,來使得每個 Map 處理的資料量減少,從而提高任務的執行效率

4.2 小檔案進行合併

在 Map 執行前合併小檔案,減少 Map 數:

set hive.input.format= org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

在 Map-Reduce 的任務結束時合併小檔案的設定

# 在 map-only 任務結束時合併小檔案
SET hive.merge.mapfiles = true;
# 在Map-Reduce任務結束時合併小檔案
SET hive.merge.mapredfiles = true;
# 合併檔案的大小,預設256M
SET hive.merge.size.per.task = 268435456;
# 當輸出檔案的平均大小小於該值時,啟動一個獨立的Map-Reduce任務進行檔案merge
SET hive.merge.smallfiles.avgsize = 16777216;

4.3 合理設定 Reduce 數

# 每個Reduce處理的資料量預設是256MB
hive.exec.reducers.bytes.per.reducer=256000000
# 每個任務最大的Reduce數,預設為1009
hive.exec.reducers.max=1009
# 計算Reduce數的公式
N=min(hive.exec.reducers.max, 資料總量/hive.exec.reducers.bytes.per.reducer)

5 並行執行

Hive 會將一個查詢轉化成一個或者多個階段,這樣的階段可以是 MapReduce 階段、抽樣階段、合併階段、limit 階段,或者 Hive 執行過程中可能需要的其他階段,預設情況下,Hive 一次只會執行一個階段,不過,某個特定的 job 可能包含眾多的階段,而這些階段可能並非完全互相依賴的,也就是說有些階段是可以並行執行的,這樣可能使得整個 job 的執行時間縮短。不過,如果有更多的階段可以並行執行,那麼 job 可能就越快完成。

通過設定引數 hive.exec.parallel 值為 true,就可以開啟併發執行。不過,在共享叢集中,需要注意下,如果 job 中並行階段增多,那麼叢集利用率就會增加。

6 嚴格模式

Hive 提供了一個嚴格模式,可以防止使用者執行那些可能意想不到的不好的影響的查詢

開啟嚴格模式需要修改 hive.mapred.mode 值為 strict,開啟嚴格模式可以禁止 種類型的查詢:

  • 對於分割槽表,除非where語句中含有分割槽欄位過濾條件來限制範圍,否則不允許執行
  • 對於使用了order by語句的查詢,要求必須使用limit語句
  • 限制笛卡爾積的查詢

7 JVM 重用

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

Hadoop 的預設配置通常是使用派生來執行和任務的,這時的啟動過程可能會造成相當大的開銷,尤其是執行的包含有成百上千任務的情況。

重用可以使得例項在同一個中重新使用多次。

需要在 Hadoop 的 mapred-site.xml 中配置,但是有個缺點是重用次數過大,會產生大量的垃圾

<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>

8 推測執行

如果使用者因為輸入資料量很大而需要執行長時間的 Map 或者 Reduce Task 的話,那麼啟動推測執行造成的浪