Hive-企業級調優
1、Fetch 抓取
Fetch 抓取是指Hive 中對某些情況的查詢可以不必使用 MapReduce 計算。例如: SELECT * FROM employees;在這種情況下,Hive 可以簡單地讀取 employee 對應的儲存目錄 下的檔案,然後輸出查詢結果到控制檯。
在 hive-default.xml.template 檔案中 hive.fetch.task.conversion 預設是 more,在全域性查詢、欄位查詢、limit 查詢等都不走 mapreduce。
案例實操:
1)把 hive.fetch.task.conversion 設定成 none,然後執行查詢語句,都會執行 mapreduce 程式。
2)把 hive.fetch.task.conversion 設定成 more,然後執行查詢語句,都不會 執行 mapreduce 程式。
一般情況下使用預設值more。
2、本地模式
大多數的 Hadoop Job 是需要 Hadoop 提供的完整的可擴充套件性來處理大資料集的。不過, 有時 Hive 的輸入資料量是非常小的。在這種情況下,為查詢觸發執行任務時消耗可能會比 實際 job 的執行時間要多的多。對於大多數這種情況,Hive 可以通過本地模式在單臺機器上 處理所有的任務。對於小資料集,執行時間可以明顯被縮短。
使用者可以通過設定 hive.exec.mode.local.auto 的值為 true,來讓 Hive 在適當的時候自動 啟動這個優化。
案例實操:
1)開啟本地模式,並執行查詢語句
2)關閉本地模式,並執行查詢語句
3、表的優化
3.1、小表、大表 Join
新版的 hive 已經對小表 JOIN 大表和大表 JOIN 小表進行了優化。小表 放在左邊和右邊已經沒有明顯區別。
3.2、大表 Join 大表
空 KEY 過濾
有時 join 超時是因為某些 key 對應的資料太多,而相同 key 對應的資料都會發送到相同 的 reducer 上,從而導致記憶體不夠。此時我們應該仔細分析這些異常的 key,很多情況下, 這些 key 對應的資料是異常資料,我們需要在 SQL 語句中進行過濾。例如 key 對應的欄位 為空,操作如下:
insert overwrite table jointable select n.* from (select * from nullidtable where id is not null ) n left join ori o on n.id = o.id;
3.3、MapJoin
MapJoin 把小表全部載入到記憶體在 map 端進行 join,避免 reducer 處理。如果不指定 MapJoin 或者不符合 MapJoin 的條件,那麼 Hive 解析器會將 Join 操作轉換成 Common Join,即:在 Reduce 階段完成 join。容易發生資料傾斜。
MapJoin預設是開啟狀態:
set hive.auto.convert.join = true; 預設為 true
大表小表的閥值設定(預設 25M 一下認為是小表):
set hive.mapjoin.smalltable.filesize=25000000;
3.4、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
3.5、Count(Distinct) 去重統計
資料量小的時候無所謂,資料量大的情況下,由於 COUNT DISTINCT 操作需要用一個 Reduce Task 來完成,這一個 Reduce 需要處理的資料量太大,就會導致整個 Job 很難完成, 一般 COUNT DISTINCT 使用先 GROUP BY 再 COUNT 的方式替換:
(1)、設定 5 個 reduce 個數
set mapreduce.job.reduces = 5;
(2)、採用 GROUP by 去重 id
hive (default)> select count(id) from (select id from bigtable group by id) a;
雖然會多用一個 Job 來完成,但在資料量大的情況下,這個絕對是值得的。
4、資料傾斜
4.1、合理設定 Map 數
1)通常情況下,作業會通過 input 的目錄產生一個或者多個 map 任務。
主要的決定因素有:input 的檔案總個數,input 的檔案大小,叢集設定的檔案塊大小。
2)是不是 map 數越多越好?
答案是否定的。如果一個任務有很多小檔案(遠遠小於塊大小 128m),則每個小檔案 也會被當做一個塊,用一個 map 任務來完成,而一個 map 任務啟動和初始化的時間遠遠大 於邏輯處理的時間,就會造成很大的資源浪費。而且,同時可執行的 map 數是受限的。
4.2、小檔案進行合併
在 map 執行前合併小檔案,減少 map 數:CombineHiveInputFormat 具有對小檔案進行 合併的功能(系統預設的格式)
4.3、複雜檔案增加 Map 數
當 input 的檔案都很大,任務邏輯複雜,map 執行非常慢的時候,可以考慮增加 Map 數,來使得每個 map 處理的資料量減少,從而提高任務的執行效率。 增加 map 的方法為:根據 computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M 公式,調 整 maxSize 最大值。讓 maxSize 最大值低於 blocksize 就可以增加 map 的個數。
4.4、合理設定 Reduce 數
在 hadoop 的 mapred-default.xml 檔案中修改設定每個 job 的 Reduce 個數
set mapreduce.job.reduces = 15;
reduce 個數並不是越多越好?
1)過多的啟動和初始化 reduce 也會消耗時間和資源;
2)另外,有多少個 reduce,就會有多少個輸出檔案,如果生成了很多個小檔案,那麼 如果這些小檔案作為下一個任務的輸入,則也會出現小檔案過多的問題;
5、並行執行
Hive 一次只會執行一個階段。不過,某個特定的 job 可能包含眾多的階段,而這些階段可能 並非完全互相依賴的,也就是說有些階段是可以並行執行的,這樣可能使得整個 job 的執行 時間縮短。通過設定引數 hive.exec.parallel 值為 true,就可以開啟併發執行。不過,在共享叢集中, 需要注意下,如果 job 中並行階段增多,那麼叢集利用率就會增加。
set hive.exec.parallel=true; //開啟任務並行執行
set hive.exec.parallel.thread.number=16; //同一個 sql 允許最大並行度,預設為 8。
注:在系統資源比較空閒的時候才有優勢,否則,沒資源,並行也起不來。
6、嚴格模式
Hive 提供了一個嚴格模式,可以防止使用者執行那些可能意向不到的不好的影響的查詢。
通過設定屬性 hive.mapred.mode 值為預設是非嚴格模式 nonstrict 。
開啟嚴格模式可以禁止 3 種類型的查詢:
1)對於分割槽表,除非 where 語句中含有分割槽欄位過濾條件來限制範圍,否則不允許執行。
2)對於使用了 order by 語句的查詢,要求必須使用 limit 語句。
3)限制笛卡爾積的查詢。
7、JVM 重用
JVM 重用是 Hadoop 調優引數的內容,其對 Hive 的效能具有非常大的影響,特別是對 於很難避免小檔案的場景或 task 特別多的場景,這類場景大多數執行時間都很短。
Hadoop 的預設配置通常是使用派生 JVM 來執行 map 和 Reduce 任務的。這時 JVM 的 啟動過程可能會造成相當大的開銷,尤其是執行的 job包含有成百上千task任務的情況。JVM 重用可以使得 JVM 例項在同一個 job 中重新使用 N 次。
N 的值可以在 Hadoop 的 mapred-site.xml 檔案中進行配置。通常在 10-20 之間
8、推測執行
Hadoop 採用 了推測執行(Speculative Execution)機制,它根據一定的法則推測出“拖後腿”的任務,併為 這樣的任務啟動一個備份任務,讓該任務與原始任務同時處理同一份資料,並最終選用最先 成功執行完成任務的計算結果作為最終結果。
9、壓縮
略
10、執行計劃(Explain)
1)基本語法
EXPLAIN [EXTENDED | DEPENDENCY | AUTHORIZATION] query
2)案例實操
(1)檢視下面這條語句的執行計劃
hive (default)> explain select * from emp;
(2)檢視詳細執行計劃
hive (default)> explain extended select * from emp;