工作中常用的 hive 參數調優,整理如下。
通過查看線上日誌的任務日誌,可以獲取任務運行每個階段的耗時情況,結合集群的資源、任務的邏輯,可以從下面這幾個角度優化我們的任務。
有時候,並不需要調整任務的參數,可能只需要調整任務的定時即可,大任務錯峰執行,也可以優化單個任務的運行時長。
原則:
最少數據最少字段最少Job數最少讀取次數避免數據傾斜整體最優而不是局部最優(以上,最優解組合不一定是整體最優,要視情況而定。)
文件大小合理切分
這裡需要結合集群的資源來合理的設置切片大小。
# 文件分割大小
set mapreduce.input.fileinputformat.split.maxsize=536870912;
# 節點文件分割大小
set mapreduce.input.fileinputformat.split.minsize.per.node=536870912;
# 機架文件分割大小
set mapreduce.input.fileinputformat.split.minsize.per.rack=536870912;
# Reduce 文件分割大小
set hive.exec.reducers.bytes.per.reducer=536870912;
# 輸入合併
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
# 在Map-only的任務結束時合併小文件
set hive.merge.mapfiles=true;
# 在Map-reduce結束時合併小文件,(注:如果文件壓縮格式不一致必須設置為false)
set hive.merge.mapredfiles=true;
# 合併文件的大小(默認)
set hive.merge.size.per.task=104857600;
# 當輸出文件的平均大小小於該值時,啟動一個獨立的map-reduce任務進行文件merge(默認)
set hive.merge.smallfiles.avgsize=104857600;
最小數據
最小數據原則:(map階段,shuffle階段,reduce階段)
網絡開銷:map端在寫磁盤的時候採用壓縮的方式將map的輸出結果進行壓縮是一個減少網絡開銷很有效的方法
數據集大小
# 數據先過濾後使用
# Shuffle操作
# Hive Group By查詢中是否在Map端先進行聚合
set hive.map.aggr=true;
# Spill、Meger文件進行壓縮
set mapreduce.map.output.compress=true;
# 壓縮編解碼器的類名
set mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;
數據傾斜
# 是否啟用傾斜連接優化
set hive.optimize.skewjoin=true;
開啟並行
# 開啟任務並行執行
set hive.exec.parallel=true;
# 允許並行任務的最大線程數
set hive.exec.parallel.thread.number=16;
# 默認情況下,當整個MapReduce作業的所有已執行完成的Map Task任務數超過Map
# Task總數的 mapreduce.job.reduce.slowstart.completedmaps (默認為0.05) 後,ApplicationMaster便會開始調度執行Reduce Task任務。
set mapreduce.job.reduce.slowstart.completedmaps=0.05
# 個MapOutputCopier線程到已完成的Map Task任務節點上分別copy一份屬於自己的數據。
# 這些copy的數據會首先保存的內存緩衝區中,當內衝緩衝區的使用率達到一定閥值後,則寫到磁盤上。
set mapred.reduce.parallel.copies=5
內存優化
1.JVM進程跑在 container 中,mapreduce.map.java.opts 能夠通過Xmx設置JVM最大的heap的使用,一般設置為 0.75 倍的 mapreduce.map.memory.mb ,因為需要為 Java code,非JVM內存使用等預留些空間;reduce的內存設置同理。
# 設置環形緩衝區的大小,經過map處理後的鍵值對,不會立馬寫入磁盤,
# 而是暫時保存在內存中的MapOutputBuffe內部的環形數據緩衝區
set mapreduce.task.io.sort.mb=1024
# 開始 spill 的百分比
set mapreduce.map.sort.spill.percent=0.8
# 設置 Map 的內存大小以及 JVM Heap
set mapreduce.map.memory.mb=4096
set mapreduce.map.java.opts=-Xmx3072M
# 設置 Reduce 的內存大小以及 JVM Heap
set mapreduce.reduce.memory.mb=4096
set mapreduce.reduce.java.opts=-Xmx3072M
# shuffile在reduce內存中的數據最多使用內存量
mapred.job.shuffle.input.buffer.percent=0.7
磁盤優化
磁盤的頻繁IO也是一種不小的消耗,所以可以通過配置一些參數來減少磁盤的IO
# 默認代表進行merge的時候最多能同時merge多少spill
# 如果有100個spill個文件,此時就無法一次完成整個merge的過程
# 這個時候需要調大來減少merge的次數,從而減少磁盤的操作;
set mapreduce.task.io.sort.factor=10
# Combiner存在的時候,此時會根據Combiner定義的函數對map的結果進行合併,什麼時候進行Combiner操作呢???
# 和Map在一個JVM中,是由min.num.spill.for.combine的參數決定的,默認是3,
# 也就是說spill的文件數在默認情況下由三個的時候就要進行combine操作,最終減少磁盤數據;
set min.num.spill.for.combine=3
# 減少磁盤IO和網絡IO還可以進行:壓縮,對spill,merge文件都可以進行壓縮。
# 中間結果非常的大,IO成為瓶頸的時候壓縮就非常有用,可以通過mapreduce.map.output.compress(default:false)設置為true進行壓縮,
# 數據會被壓縮寫入磁盤,讀數據讀的是壓縮數據需要解壓,在實際經驗中Hive在Hadoop的運行的瓶頸一般都是IO而不是CPU,壓縮一般可以10倍的減少IO操作,
# 壓縮的方式Gzip,Lzo,BZip2,Lzma等,其中Lzo是一種比較平衡選擇,mapreduce.map.output.compress.codec(default:org.apache.hadoop.io.compress.DefaultCodec)參數設置。
# 但這個過程會消耗CPU,適合IO瓶頸比較大。
set mapreduce.map.output.compress=true
mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec
資源參數
# 指定資源隊列,root.urgent
set mapred.job.queue.name=root.default;
# 最小可申請內存量
set yarn.scheduler.minimum-allocation-mb=1024;
# 最大可申請內存量
set yarn.scheduler.maximum-allocation-mb=32768;
# 最小可申請CPU數
set yarn.scheduler.minimum-allocation-vcores=1;
# 最大可申請CPU數
set yarn.scheduler.maximum-allocation-vcores=16;
# AM Container Heap內存大小
set yarn.app.mapreduce.am.command-opts=-Xmx2048M;
# AM Container內存大小
set yarn.app.mapreduce.am.resource.mb=4096;
# NodeManger可用內存大小
set yarn.nodemanager.resource.memory-mb=57344;
# NodeManger可用CPU數
set yarn.nodemanager.resource.cpu-vcores=16;
參考
MapReduce之Shuffle過程詳述HQL內存溢出的參數調優Yarn 虛擬內存詳解MapReduce過程詳解及其性能優化https://www.cnblogs.com/edisonchou/p/4298423.html