天天看點

Hive on Spark參數調優姿勢小結

前言

Hive on Spark是指使用Spark替代傳統MapReduce作為Hive的執行引擎,在HIVE-7292提出。Hive on Spark的效率比on MR要高不少,但是也需要合理調整參數才能最大化性能,本文簡單列舉一些調優項。為了符合實際情況,Spark也采用on YARN部署方式來說明。

Hive on Spark參數調優姿勢小結

Driver參數

該參數表示每個Executor可利用的CPU核心數。其值不宜設定過大,因為Hive的底層以HDFS存儲,而HDFS有時對高并發寫入處理不太好,容易造成race condition。根據我們的實踐,設定在3~6之間比較合理。

假設我們使用的伺服器單節點有32個CPU核心可供使用。考慮到系統基礎服務和HDFS等元件的餘量,一般會将YARN NodeManager的yarn.nodemanager.resource.cpu-vcores參數設為28,也就是YARN能夠利用其中的28核,此時将spark.executor.cores設為4最合适,最多可以正好配置設定給7個Executor而不造成浪費。又假設yarn.nodemanager.resource.cpu-vcores為26,那麼将spark.executor.cores設為5最合适,隻會剩餘1個核。

由于一個Executor需要一個YARN Container來運作,是以還需保證spark.executor.cores的值不能大于單個Container能申請到的最大核心數,即yarn.scheduler.maximum-allocation-vcores的值。

這兩個參數分别表示每個Executor可利用的堆内記憶體量和堆外記憶體量。堆内記憶體越大,Executor就能緩存更多的資料,在做諸如map join之類的操作時就會更快,但同時也會使得GC變得更麻煩。Hive官方提供了一個計算Executor總記憶體量的經驗公式,如下:

yarn.nodemanager.resource.memory-mb * (spark.executor.cores / yarn.nodemanager.resource.cpu-vcores)

其實就是按核心數的比例配置設定。在計算出來的總記憶體量中,80%~85%劃分給堆内記憶體,剩餘的劃分給堆外記憶體。

假設叢集中單節點有128G實體記憶體,yarn.nodemanager.resource.memory-mb(即單個NodeManager能夠利用的主機記憶體量)設為120G,那麼總記憶體量就是:120 * 1024 * (4 / 28) ≈ 17554MB。再按8:2比例劃分的話,最終spark.executor.memory設為約13166MB,spark.yarn.executor.memoryOverhead設為約4389MB。

與上一節同理,這兩個記憶體參數相加的總量也不能超過單個Container最多能申請到的記憶體量,即yarn.scheduler.maximum-allocation-mb。

該參數表示執行查詢時一共啟動多少個Executor執行個體,這取決于每個節點的資源配置設定情況以及叢集的節點數。若我們一共有10台32C/128G的節點,并按照上述配置(即每個節點承載7個Executor),那麼理論上講我們可以将spark.executor.instances設為70,以使叢集資源最大化利用。但是實際上一般都會适當設小一些(推薦是理論值的一半左右),因為Driver也要占用資源,并且一個YARN叢集往往還要承載除了Hive on Spark之外的其他業務。

上面所說的固定配置設定Executor數量的方式可能不太靈活,尤其是在Hive叢集面向很多使用者提供分析服務的情況下。是以更推薦将spark.dynamicAllocation.enabled參數設為true,以啟用Executor動态配置設定。

該參數表示每個Driver可利用的CPU核心數。絕大多數情況下設為1都夠用。

這兩個參數分别表示每個Driver可利用的堆内記憶體量和堆外記憶體量。根據資源富餘程度和作業的大小,一般是将總量控制在512MB~4GB之間,并且沿用Executor記憶體的“二八配置設定方式”。例如,spark.driver.memory可以設為約819MB,spark.driver.memoryOverhead設為約205MB,加起來正好1G。

絕大部分Hive參數的含義和調優方法都與on MR時相同,但仍有兩個需要注意。

我們知道,當Hive中做join操作的表有一方是小表時,如果hive.auto.convert.join和hive.auto.convert.join.noconditionaltask開關都為true(預設即如此),就會自動轉換成比較高效的map-side join。而hive.auto.convert.join.noconditionaltask.size這個參數就是map join轉化的門檻值,在Hive on MR下預設為10MB。

但是Hive on MR下統計表的大小時,使用的是資料在磁盤上存儲的近似大小,而Hive on Spark下則改用在記憶體中存儲的近似大小。由于HDFS上的資料很有可能被壓縮或序列化,使得大小減小,是以由MR遷移到Spark時要适當調高這個參數,以保證map join正常轉換。一般會設為100~200MB左右,如果記憶體充裕,可以更大點。

小檔案是HDFS的天敵,是以Hive原生提供了合并小檔案的選項,在on  MR時是hive.merge.mapredfiles,但是on Spark時會改成hive.merge.sparkfiles,注意要把這個參數設為true。至于小檔案合并的門檻值參數,即hive.merge.smallfiles.avgsize與hive.merge.size.per.task都沒有變化。

繼續閱讀