主頁 > 資料庫 > Hive 在作業中的調優總結

Hive 在作業中的調優總結

2023-02-14 08:07:13 資料庫

總結了一下在以往作業中,對于Hive SQL調優的一些實際應用,是日常積累的一些優化技巧,如有出入,歡迎在評論區留言探討~

EXPLAIN 查看執行計劃

建表優化

磁區

  1. 磁區表基本操作,partitioned
  2. 二級磁區
  3. 動態磁區

分桶

  1. 分桶表基本操作,clustered
  2. 分桶表主要是抽樣查詢,找出具有代表性的結果

選擇合適的檔案格式和壓縮格式

  1. LZO,拉茲羅
  2. Snappy
  3. 壓縮速度快,壓縮比高

HiveSQL語法優化

單表查詢優化

  1. 列裁剪和磁區裁剪,全表和全列掃描效率都很差,生產環境絕對不要使用SELECT *,所謂列裁剪就是在查詢時只讀取需要的列,磁區裁剪就是只讀取需要的磁區

    • 與列裁剪優化相關的配置項是hive.optimize.cp,默認是true
    • 與磁區裁剪優化相關的則是hive.optimize.pruner,默認是true
    • HiveSQL決議階段對應的則是ColumnPruner邏輯優化器
  2. Group By 配置調整,map階段會把同一個key發給一個reduce,當一個key過大時就傾斜了,可以開啟map端預聚合,可以有效減少shuffle資料量并

    # 是否在map端聚合,默認為true
    set hive.map.aggr = true;
    
    # 在map端聚合的條數
    set hive.groupby.mapaggr.checkintervel = 100000;
    
    # 在資料傾斜的時候進行均衡負載(默認是false),開啟后會有 兩個`mr任務`,
    # 當選項設定為true時,第一個 `mr任務` 會將map輸出的結果隨機分配到`reduce`,
    # 每個`reduce`會隨機分布到`reduce`上,這樣的處理結果是會使相同的`group by key`分到不同的`reduce`上,
    # 第二個 `mr任務` 再根據預處理的結果按`group by key`分到`reduce`上,
    # 保證相同`group by key`的資料分到同一個`reduce`上,
    
    # *切記!!!* 
    # 這樣能解決資料傾斜,但是不能讓運行速度更快  
    # 在資料量小的時候,開始資料傾斜負載均衡可能反而會導致時間變長  
    # 配置項畢竟是死的,單純靠它有時不能根本上解決問題
    # 因此還是建議自行了解資料傾斜的細節,并優化查詢陳述句  
    set hive.groupby.skewindata = https://www.cnblogs.com/fx67ll/archive/2023/02/13/true;
    
  3. Vectorization,矢量計算技術,通過設定批處理的增量大小為1024行單次來達到比單行單次更好的效率

    # 開啟矢量計算  
    set hive.vectorized.execution.enabled = true;
    
    # 在reduce階段開始矢量計算  
    set hive.vectorized.execution.reduce.enabled = true;
    
  4. 多重模式,一次讀取多次插入,同一張表的插入操作優化成先from tableinsert

  5. in/exists或者join用left semi join代替(為什么替代擴展一下~)

多表查詢優化

  1. CBO優化,成本優化器,代價最小的執行計劃就是最好的執行計劃

    • join的時候表的順序關系,前面的表都會被加載到記憶體中,后面的表進行磁盤掃描
    • 通過hive.cbo.enable,自動優化hivesql中多個join的執行順序
    • 可以通過查詢一下引數,這些一般都是true,無需修改
    set hive.cbo.enable = true;
    set hive.compute.query.using.stats = true;
    set hive.stats.fetch.column.stats = true;
    set hive.stats.fetch.partition.stats = true;
    
  2. 謂詞下推(非常關鍵的一個優化),將sql陳述句中的where謂詞邏輯都盡可能提前執行,減少下游處理的資料量,
    在關系型資料庫如MySQL中,也有謂詞下推(Predicate Pushdown,PPD)的概念,
    它就是將sql陳述句中的where謂詞邏輯都盡可能提前執行,減少下游處理的資料量

    # 這個設定是默認開啟的 
    # 如果關閉了但是cbo開啟,那么關閉依然不會生效 
    # 因為cbo會自動使用更為高級的優化計劃  
    # 與它對應的邏輯優化器是PredicatePushDown
    # 該優化器就是將OperatorTree中的FilterOperator向上提
    set hive.optimize.pdd = true;
    
    # 舉個例子
    # 對forum_topic做過濾的where陳述句寫在子查詢內部,而不是外部
    select a.uid,a.event_type,b.topic_id,b.title
    from calendar_record_log a
    left outer join (
      select uid,topic_id,title from forum_topic
      where pt_date = 20220108 and length(content) >= 100
    ) b on a.uid = b.uid
    where a.pt_date = 20220108 and status = 0;
    
  3. Map Join,map join是指將join操作兩方中比較小的表直接分發到各個map行程的記憶體中,在map中進行join的操作,
    map join特別適合大小表join的情況,Hive會將build tableprobe tablemap端直接完成join程序,消滅了reduce,減少shuffle,所以會減少開銷

    • set hive.auto.convert.join = true,配置開啟,默認是true
    • 注意!!! 如果執行小表join大表,小表作為主連接的主表,所有資料都要寫出去,此時會走reduce階段,mapjoin會失效
    • 大表join小表不受影響,上一條的原因主要是因為小表join大表的時候,map階段不知道reduce的結果其他reduce是否有,
    • 所以必須在最后reduce聚合的時候再處理,就產生了reduce的開銷
    # 舉個例子
    # 在最常見的`hash join`方法中,一般總有一張相對小的表和一張相對大的表,
    # 小表叫`build table`,大表叫`probe table`  
    # Hive在決議帶join的SQL陳述句時,會默認將最后一個表作為`probe table`,
    # 將前面的表作為`build table`并試圖將它們讀進記憶體  
    # 如果表順序寫反,`probe table`在前面,引發`OOM(記憶體不足)`的風險就高了  
    # 在維度建模資料倉庫中,事實表就是`probe table`,維度表就是`build table`  
    # 假設現在要將日歷記錄事實表和記錄項編碼維度表來`join`  
    select a.event_type,a.event_code,a.event_desc,b.upload_time
    from calendar_event_code a
    inner join (
      select event_type,upload_time from calendar_record_log
      where pt_date = 20220108
    ) b on a.event_type = b.event_type;
    
  4. Map Join,大表和大表的MapReduce任務,可以使用SMB Join

    • 直接join耗時會很長,但是根據某欄位分桶后,兩個大表每一個桶就是一個小檔案,兩個表的每個小檔案的分桶欄位都應該能夠一一對應(hash值取模的結果)
    • 總結就是分而治之,注意兩個大表的分桶欄位和數量都應該保持一致
    set hive.optimize.bucketmapjoin = true;
    set hive.optimeize.bucketmapjoin.sortedmerge = true;
    hive.input.format = org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
    
  5. 多表join時key相同,這種情況會將多個join合并為一個mr 任務來處理

    # 舉個例子
    # 如果下面兩個join的條件不相同  
    # 比如改成a.event_code = c.event_code  
    # 就會拆成兩個MR job計算
    select a.event_type,a.event_code,a.event_desc,b.upload_time
    from calendar_event_code a
    inner join (
      select event_type,upload_time from calendar_record_log
      where pt_date = 20220108
    ) b on a.event_type = b.event_type
    inner join (
      select event_type,upload_time from calendar_record_log_2
      where pt_date = 20220108
    ) c on a.event_type = c.event_type;
    
  6. 笛卡爾積,在生產環境中嚴禁使用

其他查詢優化

  1. Sort By 代替 Order By,HiveQL中的order by與其他sql方言中的功能一樣,就是將結果按某欄位全域排序,這會導致所有map端資料都進入一個reducer中,
    在資料量大時可能會長時間計算不完,如果使用sort by,那么還是會視情況啟動多個reducer進行排序,并且保證每個reducer內區域有序,
    為了控制map端資料分配到reducerkey,往往還要配合distribute by一同使用,如果不加distribute by的話,map端資料就會隨機分配到reducer

    # 舉個例子
    select uid,upload_time,event_type,record_data
    from calendar_record_log
    where pt_date >= 20220108 and pt_date <= 20220131
    distribute by uid
    sort by upload_time desc,event_type desc;
    
  2. Group By代替Distinct,當要統計某一列的去重數時,如果資料量很大,count(distinct)就會非常慢,原因與order by類似,
    count(distinct)邏輯只會有很少的reducer來處理,但是這樣寫會啟動兩個mr任務(單純distinct只會啟動一個),
    所以要確保資料量大到啟動mr任務overhead遠小于計算耗時,才考慮這種方法,當資料集很小或者key的傾斜比較明顯時,group by還可能會比distinct

資料傾斜

注意要和資料過量的情況區分開,資料傾斜是大部分任務都已經執行完畢,但是某一個任務或者少數幾個任務,一直未能完成,甚至執行失敗,
而資料過量,是大部分任務都執行的很慢,這種情況需要通過擴充執行資源的方式來加快速度,大資料編程不怕資料量大,就怕資料傾斜,一旦資料傾斜,嚴重影響效率

單表攜帶了 Group By 欄位的查詢

  1. 任務中存在group by操作,同時聚合函式為countsum,單個key導致的資料傾斜可以這樣通過設定開啟map端預聚合引數的方式來處理
    # 是否在map端聚合,默認為true
    set hive.map.aggr = true;
    
    # 在map端聚合的條數
    set hive.groupby.mapaggr.checkintervel = 100000;
    
    # 有資料傾斜的時候開啟負載均衡,這樣會生成兩個mr任務
    set hive.groupby.skewindata = https://www.cnblogs.com/fx67ll/archive/2023/02/13/true;
    
  2. 任務中存在group by操作,同時聚合函式為countsum,多個key導致的資料傾斜可以通過增加reduce的數量來處理
    • 增加磁區可以減少不同磁區之間的資料量差距,而且增加的磁區時候不能是之前磁區數量的倍數,不然會導致取模結果相同繼續分在相同磁區
    • 第一種修改方式
    # 每個reduce處理的數量
    set hive.exec.reduce.bytes.per.reducer = 256000000;
    
    # 每個任務最大的reduce數量
    set hive.exec.reducers.max = 1009;
    
    # 計算reducer數的公式,根據任務的需要調整每個任務最大的reduce數量  
    N = min(設定的最大數,總數量數/每個reduce處理的數量)
    
    • 第二種修改方式
    # 在hadoop的mapred-default.xml檔案中修改
    set mapreduce.job.reduces = 15;
    

兩表或多表的 join 關聯時,其中一個表較小,但是 key 集中

  1. 設定引數增加map數量
    # join的key對應記錄條數超過該數量,會進行分拆  
    set hive.skewjoin.key = 1000;
    
    # 并設定該引數為true,默認是false
    set hive.optimize.skewjoin = true;
    
    # 上面的引數如果開啟了會將計算數量超過閾值的key寫進臨時檔案,再啟動另外一個任務做map join  
    # 可以通過設定這個引數,控制第二個任務的mapper數量,默認10000
    set hive.skewjoin.mapjoin.map.tasks = 10000;
    
  2. 使用mapjoin,減少reduce從根本上解決資料傾斜,參考HiveSQL語法優化 -> 多表查詢優化 -> Map Join,大表和大表的MapReduce任務,SMB Join

兩表或多表的 join 關聯時,有 Null值 或 無意義值

這種情況很常見,比如當事實表是日志類資料時,往往會有一些項沒有記錄到,我們視情況會將它置為null,或者空字串-1等,
如果缺失的項很多,在做join時這些空值就會非常集中,拖累進度,因此,若不需要空值資料,就提前寫where陳述句過濾掉,
需要保留的話,將空值key用隨機方式打散,例如將用戶ID為null的記錄隨機改為負值

select a.uid,a.event_type,b.nickname,b.age
from (
  select 
  (case when uid is null then cast(rand()*-10240 as int) else uid end) as uid,
  event_type from calendar_record_log
  where pt_date >= 20220108
) a left outer join (
  select uid,nickname,age from user_info where status = 4
) b on a.uid = b.uid;

兩表或多表的 join 關聯時,資料型別不統一

比如int型別和string型別進行關聯,關聯時候以小型別作為磁區,這里intstring會到一個reduceTask中,如果資料量多,會造成資料傾斜

# 可以通過轉換為同一的型別來處理
cast(user.id as string)

單獨處理傾斜key

這其實是上面處理空值方法的拓展,不過傾斜的key變成了有意義的,一般來講傾斜的key都很少,我們可以將它們抽樣出來,
對應的行單獨存入臨時表中,然后打上一個較小的亂數前綴(比如0~9),最后再進行聚合

Hive Job 優化

Hive Map 優化

Map數量多少的影響

  1. Map數過大
    • map階段輸出檔案太小,產生大量小檔案
    • 初始化和創建map的開銷很大
  2. Map數太小
    • 檔案處理或查詢并發度小,Job執行時間過長
    • 大量作業時,容易堵塞集群

控制Map數的原則

根據實際情況,控制map數量需要遵循兩個原則

  1. 第一是使大資料量利用合適的map
  2. 第二是使單個map任務處理合適的資料量

復雜檔案適當增加Map數

  1. input的檔案都很大,任務邏輯復雜,map執行非常慢的時候,可以考慮增加map數,來使得每個map處理的資料量減少,從而提高任務的執行效率
  2. 那么如何增加map的數量呢?在map階段,檔案先被切分成split塊,而后每一個split切片對應一個Mapper任務
    FileInputFormat這個類先對輸入檔案進行邏輯上的劃分,以128m為單位,將原始資料從邏輯上分割成若干個split,每個split切片對應一個mapper任務
    所以說減少切片的大小就可增加map數量
  3. 可以依據公式計算computeSliteSize(Math.max(minSize, Math.min(maxSize, blockSize))) = blockSize = 128m
  4. 執行陳述句:set mapreduce.input.fileinputformat.split.maxsize = 100;

小檔案進行合并減少Map數

為什么要進行小檔案合并?因為如果一個任務有很多小檔案(遠遠小于塊大小128m),則每個小檔案也會被當做一個塊,用一個map任務來完成,
而一個map任務啟動和初始化的時間遠遠大于邏輯處理的時間,就會造成很大的資源浪費,同時可執行的map數是受限的
兩種方式合并小檔案

  1. Map執行前合并小檔案,減少map數量
    // 每個Map最大輸入大小(這個值決定了合并后檔案的數量)
    set mapred.max.split.size = 256000000;
    
    // 一個節點上split的至少的大小(這個值決定了多個DataNode上的檔案是否需要合并)
    set mapred.min.split.size.per.node = 100000000;
    
    // 一個交換機下split的至少的大小(這個值決定了多個交換機上的檔案是否需要合并)
    set mapred.min.split.size.per.rack = 100000000;
    
    // 執行Map前進行小檔案合并
    set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
    
  2. Map-Reduce任務執行結束時合并小檔案,減少小檔案輸出
    // 設定map端輸出進行合并,默認為true
    set hive.merge.mapfiles = true;
    
    // 設定reduce端輸出進行合并,默認為false
    set hive.merge.mapredfiles = true;
    
    // 設定合并檔案的大小,默認是256
    set hive.merge.size.per.task = 256 * 1000 * 1000;
    
    // 當輸出檔案的平均大小小于該值時,啟動一個獨立的`MapReduce任務`進行檔案`merge`,
    set hive.merge.smallfiles.avgsize = 16000000;
    

Map端預聚合減少Map數量

  1. 相當于在map端執行combiner,執行命令:set hive.map.aggr = true;
  2. combiners是對map端的資料進行適當的聚合,其好處是減少了從map端到reduce端的資料傳輸量
  3. 其作用的本質,是將map計算的結果進行二次聚合,使Key-Value<List>List的資料量變小,從而達到減少資料量的目的

推測執行

  1. 在分布式集群環境下,因為程式Bug(包括Hadoop本身的bug),負載不均衡或者資源分布不均等原因,會造成同一個作業的多個任務之間運行速度不一致,
    有些任務的運行速度可能明顯慢于其他任務(比如一個作業的某個任務進度只有50%,而其他所有任務已經運行完畢),則這些任務會拖慢作業的整體執行進度
  2. Hadoop采用了推測執行(Speculative Execution)機制,它根據一定的法則推測出拖后腿的任務,并為這樣的任務啟動一個備份任務,
    讓該任務與原始任務同時處理同一份資料,并最終選用最先成功運行完成任務的計算結果作為最終結果
  3. 執行命令:set mapred.reduce.tasks.speculative.execution = true; # 默認是true
  4. 當然,如果用戶對于運行時的偏差非常敏感的話,那么可以將這些功能關閉掉,如果用戶因為輸入資料量很大而需要執行長時間的map task或者reduce task的話,
    那么啟動推測執行造成的浪費是非常巨大的

合理控制Map數量的實際案例

假設一個SQL任務:

SELECT COUNT(1) 
FROM fx67ll_alarm_count_copy
WHERE alarm_date = "2021-01-08";

該任務的輸入目錄inputdir是:/group/fx67ll_data/fx67ll_data_etl/date/fx67ll_alarm_count_copy/alarm_date=2021-01-08,共有194個檔案,
其中很多是遠遠小于128m的小檔案,總大小約9G,正常執行會用194個Map任務map總共消耗的計算資源:SLOTS_MILLIS_MAPS= 610,023
通過在Map執行前合并小檔案,減少Map數

# 前面三個引數確定合并檔案塊的大小
# 大于檔案塊大小128m的,按照128m來分隔 
# 小于128m,大于100m的,按照100m來分隔
# 把那些小于100m的(包括小檔案和分隔大檔案剩下的),進行合并,最終生成了74個塊
set mapred.max.split.size=100000000;
set mapred.min.split.size.per.node=100000000;
set mapred.min.split.size.per.rack=100000000;
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

合并后,用了74個map任務,map消耗的計算資源:SLOTS_MILLIS_MAPS= 323,098,對于這個簡單SQL任務,執行時間上可能差不多,但節省了一半的計算資源

再假設這樣一個SQL任務:

SELECT data_fx67ll,
COUNT(1),
COUNT(DISTINCT id),
SUM(CASE WHEN …),
SUM(CASE WHEN …),
SUM(…)
FROM fx67ll_device_info_zs
GROUP data_fx67ll

如果表fx67ll_device_info_zs只有一個檔案,大小為120m,但包含幾千萬的記錄,如果用1個map去完成這個任務,肯定是比較耗時的,
這種情況下,我們要考慮將這一個檔案合理的拆分成多個
增加Reduce數量,來增加Map數量

set mapred.reduce.tasks=10;
CREATE TABLE fx67ll_device_info_zs_temp
AS
SELECT * 
FROM fx67ll_device_info_zs
DISTRIBUTE BY RAND(123);

這樣會將fx67ll_device_info_zs表的記錄,隨機的分散到包含10個檔案的fx67ll_device_info_zs_temp表中,
再用fx67ll_device_info_zs_temp代替上面sql中的fx67ll_device_info_zs表,
則會用10個map任務去完成,每個map任務處理大于12m(幾百萬記錄)的資料,效率肯定會好很多

Hive Reduce 優化

Reduce數量多少的影響

  1. map一樣,啟動和初始化reduce也會消耗時間和資源
  2. 另外,有多少個reduce,就會有多少個輸出檔案,如果生成了很多個小檔案,那么如果這些小檔案作為下一個任務的輸入,則也會出現小檔案過多的問題

控制Reduce數的原則

map一樣,控制reduce數量需要遵循兩個原則

  1. 第一是使大資料量利用合適的reduce
  2. 第二是使單個reduce任務處理合適的數據量

Hive自己如何確定Reduce數

reduce個數的設定極大影響任務執行效率,不指定reduce個數的情況下,Hive會猜測確定一個reduce個數,基于以下兩個設定:

# 每個reduce任務處理的資料量,默認為 1000^3=1G
hive.exec.reducers.bytes.per.reducer

# 每個任務最大的reduce數,默認為999
hive.exec.reducers.max

計算reducer數的公式很簡單N = min(引數2,總輸入資料量 / 引數1)
即,如果reduce的輸入(map的輸出)總大小不超過1G,那么只會有一個reduce任務

舉個例子:

SELECT alarm_date,
		COUNT(1) 
FROM fx67ll_alarm_count_copy
WHERE alarm_date = "2021-01-08"
GROUP BY alarm_date;

該任務的輸入目錄inputdir是:/group/fx67ll_data/fx67ll_data_etl/date/fx67ll_alarm_count_copy/alarm_date=2021-01-08
總大小為9G多,因此這句有10個reduce

如何調整Reduce數量

注意!!!實際開發中,reduce的個數一般通程序式自動推定,而不人為干涉,因為人為控制的話,如果使用不當很容易造成結果不準確,且降低執行效率

  1. 通過調整每個reduce任務處理的資料量來調整reduce個數,處理的資料量少了,任務數就多了
    # 設定每個reduce任務處理的資料量500M,默認是1G
    set hive.exec.reducers.bytes.per.reducer = 500000000;
    
    SELECT alarm_date,
    		COUNT(1) 
    FROM fx67ll_alarm_count_copy
    WHERE alarm_date = "2021-01-08"
    GROUP BY alarm_date;
    
    這次有20個reduce
    
  2. 直接調整每個Job中的最大reduce數量,過于簡單粗暴,慎用,盡量不要,雖然設定了reduce的個數看起來好像執行速度變快了,但是實際并不是這樣的
    # 設定每個任務最大的reduce數為15個,默認為999
    set mapred.reduce.tasks = 15;
    
    SELECT alarm_date,
    		COUNT(1) 
    FROM fx67ll_alarm_count_copy
    WHERE alarm_date = "2021-01-08"
    GROUP BY alarm_date;
    
    這次有15個reduce
    

推測執行

參考map優化的最后一項

什么情況下只有一個Reduce

很多時候你會發現任務中不管資料量多大,不管你有沒有設定調整reduce個數的引數,任務中一直都只有一個reduce任務,
其實只有一個reduce任務的情況,除了資料量小于hive.exec.reducers.bytes.per.reducer引數值的情況外,還有以下原因:

  1. 沒有Group By的匯總,例如:
    SELECT alarm_date,
    		COUNT(1) 
    FROM fx67ll_alarm_count_copy
    WHERE alarm_date = "2021-01-08"
    GROUP BY alarm_date;
    
    寫成
    
    SELECT COUNT(1) 
    FROM fx67ll_alarm_count_copy
    WHERE alarm_date = "2021-01-08";
    
    注意避免這樣情況的發生
    
  2. 用了Order by排序,因為它會對資料進行全域排序,所以資料量特別大的時候效率非常低,盡量避免
  3. 有笛卡爾積,生產環境必須嚴格避免

Hive 任務整體優化

Fetch抓取

Fetch抓取是指Hive在某些情況的查詢可以不必使用mr 任務,例如在執行一個簡單的select * from XX時,我們只需要簡單的進行抓取對應目錄下的資料即可,
hive-default.xml.template中,hive.fetch.task.conversion(默認是morn),老版本中默認是minimal
該屬性為morn時,在全域查找,欄位查找,limit查找等都不走mr 任務

本地模式

Hive也可以不將任務提交到集群進行運算,而是直接在一臺節點上處理,因為消除了提交到集群的overhead,所以比較適合資料量很小,且邏輯不復雜的任務,
設定hive.exec.mode.local.auto為true可以開啟本地模式,但任務的輸入資料總量必須小于hive.exec.mode.local.auto.inputbytes.max(默認值128MB)
且mapper數必須小于hive.exec.mode.local.auto.tasks.max(默認值4)reducer數必須為0或1,才會真正用本地模式執行

并行執行

Hive中互相沒有依賴關系的job間是可以并行執行的,最典型的就是多個子查詢union all
在集群資源相對充足的情況下,可以開啟并行執行,即將引數hive.exec.parallel設為true,
另外hive.exec.parallel.thread.number可以設定并行執行的執行緒數,默認為8,一般都夠用,
注意!!!沒資源無法并行,且資料量小時開啟可能還沒不開啟快,所以建議資料量大時開啟

嚴格模式

要開啟嚴格模式,需要將引數hive.mapred.mode設為strict
所謂嚴格模式,就是強制不允許用戶執行3種有風險的sql陳述句,一旦執行會直接失敗,這3種陳述句是:

  1. 查詢磁區表時不限定磁區列的陳述句
  2. 兩表join產生了笛卡爾積的陳述句
  3. 用order by來排序但沒有指定limit的陳述句

JVM重用

  1. 主要用于處理小檔案過多的時候
  2. mr 任務中,默認是每執行一個task就啟動一個JVM,如果task非常小而碎,那么JVM啟動和關閉的耗時就會很長
  3. 可以通過調節引數mapred.job.reuse.jvm.num.tasks來重用
  4. 例如將這個引數設成5,那么就代表同一個mr 任務中順序執行的5個task可以重復使用一個JVM,減少啟動和關閉的開銷,但它對不同mr 任務中的task無效

啟用壓縮

壓縮job的中間結果資料和輸出資料,可以用少量CPU時間節省很多空間,壓縮方式一般選擇Snappy,效率最高,
要啟用中間壓縮,需要設定hive.exec.compress.intermediate為true,
同時指定壓縮方式hive.intermediate.compression.codecorg.apache.hadoop.io.compress.SnappyCodec
另外,引數hive.intermediate.compression.type可以選擇對塊(BLOCK)還是記錄(RECORD)壓縮,BLOCK的壓縮率比較高,
輸出壓縮的配置基本相同,打開hive.exec.compress.output即可

采用合適的存盤格式

  1. 在Hive SQL的create table陳述句中,可以使用stored as ...指定表的存盤格式,
    Hive表支持的存盤格式有TextFileSequenceFileRCFileAvroORCParquet等,
    存盤格式一般需要根據業務進行選擇,在我們的實操中,絕大多數表都采用TextFileParquet兩種存盤格式之一,
  2. TextFile是最簡單的存盤格式,它是純文本記錄,也是Hive的默認格式,雖然它的磁盤開銷比較大,查詢效率也低,但它更多地是作為跳板來使用,
  3. RCFileORCParquet等格式的表都不能由檔案直接匯入資料,必須由TextFile來做中轉,
  4. ParquetORC都是Apache旗下的開源列式存盤格式,列式存盤比起傳統的行式存盤更適合批量OLAP查詢,并且也支持更好的壓縮和編碼,
  5. 我們選擇Parquet的原因主要是它支持Impala查詢引擎,并且我們對updatedelete事務性操作需求很低,

Hive的小檔案

什么情況下會產生小檔案?

  1. 動態磁區插入資料,產生大量的小檔案,從而導致map數量劇增
  2. reduce數量越多,小檔案也越多,有多少個reduce,就會有多少個輸出檔案,如果生成了很多小檔案,那這些小檔案作為下一次任務的輸入
  3. 資料源本身就包含大量的小檔案

小檔案有什么樣的危害?

  1. 從Hive的角度看,小檔案會開很多map,一個map開一個java虛擬機jvm去執行,所以這些任務的初始化,啟動,執行會浪費大量的資源,嚴重影響性能
  2. 在hdfs中,每個小檔案物件約占150byte,如果小檔案過多會占用大量記憶體,這樣NameNode記憶體容量嚴重制約了集群的擴展
    • 每個hdfs上的檔案,會消耗128位元組記錄其meta資訊,所以大量小檔案會占用大量記憶體

如何避免小檔案帶來的危害?

從小檔案產生的途經就可以從源頭上控制小檔案數量

  1. 使用Sequencefile作為表存盤格式,不要用textfile,在一定程度上可以減少小檔案
  2. 減少reduce的數量(可以使用引數進行控制)
  3. 少用動態磁區,用時記得按distribute by磁區

對于已有的小檔案

  1. 使用hadoop archive命令把小檔案進行歸檔,采用archive命令不會減少檔案存盤大小,只會壓縮NameNode的空間使用
  2. 重建表,建表時減少reduce數量

我是 fx67ll.com,如果您發現本文有什么錯誤,歡迎在評論區討論指正,感謝您的閱讀!
如果您喜歡這篇文章,歡迎訪問我的 本文github倉庫地址,為我點一顆Star,Thanks~ ??
轉發請注明參考文章地址,非常感謝!!!

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/543825.html

標籤:其他

上一篇:HiveSQL 作業實戰總結

下一篇:GaussDB(DWS)遷移:一種執行高效的TereData的marco遷移方案

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more