Hive高級優化的各種方法

1:壓縮

首先打開hive的壓縮功能

命令:set hive.exec.compress.intermediate=true;

在這裏插入圖片描述

開啓map端數據壓縮功能

命令:set mapreduce.map.output.compress=true;
在這裏插入圖片描述

設置map端的數據壓縮格式:

命令:set mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;

===》 設置成大數據常用的壓縮格式:Snappy格式

設置reduce端的數據壓縮格式:

命令:set mapreduce.output.fileoutputformat.compass=true;

設置Reduce端的數據壓縮格式:set mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.ip.compress.SnappyCodec;

設置類型:set mapreduce.output.fileoutputformat.compress.type=BLOCK;

2:存儲格式

​ hive存儲格式: TextFile ,SequenceFile,orc,Parquet (後面兩種是列存儲)

首先在hive中根據文件字段創建一個表,並存儲爲orc的格式

create table itstar_log(time string,host string)row format delimited fields terminated by “\t”

stored as orc;

將 itstar1中的數據導入到 itstar_log中(注意itstar1的數據類型必須一樣)

insert into table itstar_log1 select * from itstar1 limit 10;
在這裏插入圖片描述

原始數據 itstar_log是482.26kb
在這裏插入圖片描述

修改存儲格式後的數據時660B.

存儲格式不一樣,佔空間大小不一樣。

同時查詢時間不一樣:

如:select count(1) from itstar1 的時間會大於修改存儲格式後的 select count(1) from itstar_log1;查詢時間

3:hive數據傾斜

​ **問題:**分組mr程序,map階段把相同的key的數據都分發給一個reduce,一個key的量很大。

解決方案:

  • 設置map聚合:set hive.map.aggr=true;

  • 設置負載均衡:set hive.groupby.skewindata=true;

  • 合理避免數據傾斜:設置合理map數;合併小文件

  • JVM重用:mapreduce.job.jvm.numtasks: 設置10-20之間

4:FetchTask

​ 不執行mapreduce,提高速度
​ 設置的三種方式:

方法1:

set hive.fetch.task.conversion=more;

方法2:

bin/hive --hiveconf hive.fetch.task.conversion=more

上面的兩種方法都可以開啓了Fetch任務,但是都是臨時起作用的;如果你想一直啓用這個功能,可以在${HIVE_HOME}/conf/hive-site.xml

<property>

<name>hive.fetch.task.conversion</name>

<value>minimal</value>

<description>

Some select queries can be converted to single FETCH task minimizing latency.

Currently the query should be single sourced not having any subquery and should not have

any aggregations or distincts (which incurs RS), lateral views and joins.

1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only

2. more : SELECT, FILTER, LIMIT only (TABLESAMPLE, virtual columns)

</description>

</property>

5:大表拆分成子表

5.1 背景

一個日誌文件中,每一行記錄,會有很多很多字段,四五十個字段很正常.實際分析中,常常使用少數幾個字段

5.2 方式

將原始的表中數據,依據業務需求提取出要分析的字段,數據放入到對應的業務表(子表)中,實際的業務針對業務表進行分析。

5.3 舉例

在實際中,我們會發現,有些業務處理,會有共同數據集
用戶表、訂單表、商品表,三個表需要進行join的操作
|
| join 會產生一個結果集
|
會有很多的業務是針對此jion結果集進行分析
業務一:
join
結論:
將衆多的業務中相同的中間結果集,抽取到一個Hive中的表中去

5.4 外部表、分區表

外部表、分區表
結合使用
多級分區

數據
存儲格式(textfile、orcfile、parquet)
數據壓縮(snappy)

6:JVM重用

JVM重用是hadoop調優參數的內容,對hive的性能具有非常大的影響,特別是對於很難避免小文件的場景或者task特別多的場景,這類場景大多數執行時間都很短。hadoop默認配置是使用派生JVM來執行map和reduce任務的,這是jvm的啓動過程可能會造成相當大的開銷,尤其是執行的job包含有成千上萬個task任務的情況。
JVM重用可以使得JVM實例在同一個JOB中重新使用N次,N的值可以在Hadoop的mapre-site.xml文件中進行設置

mapred.job.reuse.jvm.num.tasks 1

也可在hive的執行設置:

set  mapred.job.reuse.jvm.num.tasks=10; //一個java虛擬機可以被多個job使用.通常設置成八個

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

7:推測執行

推測式任務,也叫做Speculative task。它是一種以空間換時間的策略。
當所有task都開始運行之後,任務對應的ApplicationMaster會統計所有任務的平均進度,如果某個task所在的task node機器配置比較低或者CPU load很高(原因很多),導致任務執行比總體任務的平均執行要慢,
此時AM會啓動一個新的任務(Speculative task),原有任務和新任務哪個先執行完就把另外一個kill掉,
這也是我們經常在RM頁面看到任務執行成功,但是總有些task被kill,就是這個原因。
目的:是通過加快獲取單個 task 的結果以及進行偵測將執行慢的 TaskTracker 加入到黑名單的方式來提高整體的任務執行效率

(1)修改$HADOOP_HOME/conf/mapred-site.xml 文件

<property>

<name>mapred.map.tasks.speculative.execution </name>

<value>true</value>

</property>

<property>

<name>mapred.reduce.tasks.speculative.execution </name>

<value>true</value>

</property>

(2)修改hive 配置

set hive.mapred.reduce.tasks.speculative.execution=true;

8:Map數目

dfs.block.size=268435456

hive.merge.mapfiles=true

hive.merge.mapredfiles=true

hive.merge.size.per.task=256000000

mapred.map.tasks=2

因爲合併小文件默認爲true,而dfs.block.size與hive.merge.size.per.task的搭配使得合併後的絕大部分文件都在300MB左右。
CASE 1:
現在我們假設有3個300MB大小的文件,那麼goalsize = min(900MB/2,256MB) = 256MB
所以整個JOB會有6個map,其中3個map分別處理256MB的數據,還有3個map分別處理44MB的數據。
這時候木桶效應就來了,整個JOB的map階段的執行時間不是看最短的1個map的執行時間,而是看最長的1個map的執行時間。所以,雖然有3個map分別只處理44MB的數據,可以很快跑完,但它們還是要等待另外3個處理256MB的map。顯然,處理256MB的3個map拖了整個JOB的後腿。
CASE 2:
如果我們把mapred.map.tasks設置成6,再來看一下有什麼變化:goalsize = min(900MB/6,256MB) = 150MB
整個JOB同樣會分配6個map來處理,每個map處理150MB的數據,非常均勻,誰都不會拖後腿,最合理地分配了資源,執行時間大約爲CASE 1的59%(150/256)
案例分析:
雖然mapred.map.tasks從2調整到了6,但是CASE 2並沒有比CASE 1多用map資源,同樣都是使用6個map。而CASE 2的執行時間約爲CASE 1執行時間的59%。
從這個案例可以看出,對mapred.map.tasks進行自動化的優化設置其實是可以很明顯地提高作業執行效率的。

要求:文件數據壓縮的方式爲可分割的,比如BZip2Codec。或者文件數據本身沒有用壓縮。

9:設置Redeuce數目

9.1 reduce個數

參數1:hive.exec.reducers.bytes.per.reducer=256000000:每個reduce任務處理的數據量
參數2:hive.exec.reducers.max=1009:每個任務最大的reduce數目
計算公式:reducer個數=min(參數2,總輸入數據量/參數1)
 set mapred.reduce.tasks =N:
每個任務默認的reduce數目。典型爲0.99*reduce槽數,hive默認爲-1,即自動確定reduce數目。

reduce個數並不是越多越好
同map一樣,啓動和初始化reduce也會消耗時間和資源;
另外,有多少個reduce,就會有多少個輸出文件,如果生成了很多個小文件,那麼如果這些小文件作爲下一個任務的輸入,則也會出現小文件過多的問題

9.2 什麼情況下只有一個reduce

​ 很多時候你會發現任務中不管數據量多大,不管你有沒有設置調整reduce個數的參數,任務中一直都只有一個reduce任務;
其實只有一個reduce任務的情況,除了數據量小於
hive.exec.reducers.bytes.per.reducer參數值的情況外,還有以下原因:
a) 沒有group by的彙總
b) 用了Order by

10:並行執行

​ 並行執行,意思是同步執行hive的多個階段,hive在執行過程,將一個查詢轉化成一個或者多個階段。某個特定的job可能包含衆多的階段,而這些階段可能並非完全相互依賴的,也就是說可以並行執行的,這樣可能使得整個job的執行時間縮短

hive.exec.parallel.thread.number 8//job並行執行的數目,一個SQL語句可能有很多mapreduce任務,限制

hive.exec.parallel false

hive執行開啓:

set hive.exec.parallel=true

11:其他等方法

還有explain執行計劃;嚴格模式避免出現笛卡爾積等不好的結果;還有小數據量開啓本地模式等等

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