Hive優(yōu)化

Hive優(yōu)化

今天的主要內(nèi)容——Hive優(yōu)化

  • Fetch抓取

    • Hive 中對某些情況的查詢可以不必使用 MapReduce 計(jì)算
  • 本地模式

    • 當(dāng)數(shù)據(jù)量非常小的時(shí)候,通過設(shè)置本地模式在單臺機(jī)器上處理所有任務(wù),可提高效率
  • 表的優(yōu)化

    • 小表join大表

    • 大表join大表

      • 空KEY過濾

      • 空Key轉(zhuǎn)化

    • MapJoin

      • 注意:MapJoin的工作機(jī)制

      • mapjoin對分桶表join的優(yōu)化

    • Group By

      • Map端的聚合
    • Count(Distinct) 去重統(tǒng)計(jì)

      • 一般 COUNT DISTINCT 使用先 GROUP BY 再 COUNT 的方式替換
    • 笛卡爾積

      • 避免使用笛卡爾積
    • 行列過濾

      • 避免使用select *

      • 通過子查詢后,再關(guān)聯(lián)表

    • 動(dòng)態(tài)分區(qū)的調(diào)整

      • 注意動(dòng)態(tài)分區(qū)的語法
    • 分桶

      • 分桶的理解以及插入數(shù)據(jù)時(shí)注意事項(xiàng)
    • 分區(qū)

      • 分區(qū)的理解
    • left semi join

      • 對 in/exists的子查詢提供了更高效的優(yōu)化方式
    • insert into 代替 union all

  • 數(shù)據(jù)傾斜

    • 合理設(shè)置Map數(shù)量

    • 小文件合并

    • 復(fù)雜文件增加Map數(shù)

    • 合理設(shè)置Reduce數(shù)量

  • 并行執(zhí)行

  • 嚴(yán)格模式

  • JVM重用(同一個(gè)job中的tasks)

  • 推測執(zhí)行

  • 壓縮

  • 執(zhí)行計(jì)劃

一、Fetch抓取

  • 概念:

    • Fetch 抓取是指,Hive 中對某些情況的查詢可以不必使用 MapReduce 計(jì)算。

    • 例如:

      • SELECT * FROM emp;

      • 在這種情況下,Hive 可以簡單地讀取 emp 對應(yīng)的存儲目錄下的文件,然后輸出查詢結(jié)果到控制臺。

  • 操作

    • 在 hive-default.xml.template 文件中 hive.fetch.task.conversion屬性值設(shè)置

    • 修改屬性值:

      • hive.fetch.task.conversion

        • CDH5.3.6中對應(yīng)的hive 0.13.1中,該屬性值默認(rèn)為minimal

        • 之后新版中該屬性值默認(rèn)為more

             * none : disable hive.fetch.task.conversion
             
            * minimal : SELECT STAR, FILTER on partition columns, LIMIT only
                
                * minimal格式下:只有select * ; filter分區(qū)列過濾 下不走M(jìn)R
          
             * more : SELECT, FILTER, LIMIT only (support TABLESAMPLE and virtual columns)
          
                * more格式下:select;filter;limit不走M(jìn)R
          

二、本地模式(小任務(wù))

  • 概念

    • 當(dāng)數(shù)據(jù)量非常小時(shí),在這種情況下,為查詢觸發(fā)執(zhí)行任務(wù)時(shí)消耗可能會(huì)比實(shí)際 job 的執(zhí)行時(shí)間要多的多。

    • 可以聯(lián)系到hadoop運(yùn)行MapReduce job時(shí)候:

      • 當(dāng)job很小時(shí),application master會(huì)在自己的本地虛擬機(jī)中運(yùn)行tasks,這時(shí)相比較于allocating and running in new containers的成本而言的,也就是說相比較于開啟一個(gè)新的container并耗費(fèi)資源拉取數(shù)據(jù)的時(shí)間比job執(zhí)行時(shí)間都長。
    • 滿足以下條件時(shí),可以使Hive 通過本地模式在單臺機(jī)器上處理所有的任務(wù)。

      • job的輸入數(shù)據(jù)大小必須小于參數(shù):hive.exec.mode.local.auto.inputbytes.max(默認(rèn)128MB)

      • 輸入文件的個(gè)數(shù)必須小于參數(shù)hive.exec.mode.local.auto.input.files.max,默認(rèn)為4

      • job的reduce數(shù)必須為0或者1

  • 操作

    • set hive.exec.mode.local.auto=true; //開啟本地 mr

    • set hive.exec.mode.local.auto.inputbytes.max=50000000;

      • 設(shè)置 local mr 的最大輸入數(shù)據(jù)量,當(dāng)輸入數(shù)據(jù)量小于這個(gè)值時(shí)采用 local mr 的方式,默認(rèn)為 134217728,即 128M
    • set hive.exec.mode.local.auto.input.files.max=10;

      • 設(shè)置 local mr 的最大輸入文件個(gè)數(shù),當(dāng)輸入文件個(gè)數(shù)小于這個(gè)值時(shí)采用 local mr 的方式,默認(rèn)為 4

三、表的優(yōu)化

1. 小表join大表

  • 概念

    • 大表放在后面

      • hive在處理每一個(gè)MR階段的join時(shí),the last table in the sequence is streamed through the reducers whereas the others are buffered。即最后一張表是通過reducer拉取數(shù)據(jù)得到的,而前面的表均是緩存到內(nèi)存中的,因此,為了減少reducer內(nèi)存的使用,選擇將數(shù)據(jù)量大的表放在最后邊,其他表緩存到reducer中)

      • 因此通常需要將小表放前面,或者標(biāo)記哪張表是大表:/*streamtable(table_name) */

      • 將 key 相對分散,并且數(shù)據(jù)量小的表放在 join 的左邊,這樣可以有效減少內(nèi)存溢出錯(cuò)誤發(fā)生的幾率;再進(jìn)一步,可以使用 Group 讓小的維度表(1000 條以下的記錄條數(shù))先進(jìn)內(nèi)存。在 map 端完成 reduce。(也就是開啟map端的聚合)、

    • 使用相同連接鍵

      • 首先要明白: hive是將joins轉(zhuǎn)化為MR任務(wù)去執(zhí)行的,當(dāng)多張表的連接條件為同一個(gè)join clause則開啟一個(gè)MR任務(wù),當(dāng)不同的join clauses時(shí),則開啟多個(gè)MR任務(wù)。

      • 因此,當(dāng)對3個(gè)或者更多個(gè)表進(jìn)行join連接時(shí),如果每個(gè)on子句都使用相同的連接鍵的話,那么只會(huì)產(chǎn)生一個(gè)MapReduce job。

    • 實(shí)際測試發(fā)現(xiàn):新版的 hive 已經(jīng)對小表 JOIN 大表和大表 JOIN 小表進(jìn)行了優(yōu)化。小表放在左邊和右邊已經(jīng)沒有明顯區(qū)別。

    • 其實(shí)開啟map端join后,還可以避免數(shù)據(jù)傾斜問題

  • 操作

    • 設(shè)置屬性值hive.auto.convert.join,默認(rèn)為true

2. 大表join大表

2.1 空KEY過濾

  • 概念

    • 有時(shí) join 超時(shí)是因?yàn)槟承?key 對應(yīng)的數(shù)據(jù)太多,而相同 key 對應(yīng)的數(shù)據(jù)都會(huì)發(fā)送到相同的 reducer 上,從而導(dǎo)致內(nèi)存不夠,

    • 此時(shí)我們應(yīng)該仔細(xì)分析這些異常的 key,很多情況下,這些 key 對應(yīng)的數(shù)據(jù)是異常數(shù)據(jù),我們需要在 SQL 語句中進(jìn)行過濾。例如 key 對應(yīng)的字段為空

        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;
      

2.2 空KEY轉(zhuǎn)化

  • 概念

    • 有時(shí)雖然某個(gè) key 為空對應(yīng)的數(shù)據(jù)很多,但是相應(yīng)的數(shù)據(jù)不是異常數(shù)據(jù),必須要包含在join 的結(jié)果中,此時(shí)我們可以表 a 中 key 為空的字段賦一個(gè)隨機(jī)的值,使得數(shù)據(jù)隨機(jī)均勻地分不到不同的 reducer 上。

    • 此時(shí)注意:空key表full join表,防止數(shù)據(jù)丟失

  • 操作

    • 設(shè)置reduce個(gè)數(shù)

      set mapreduce.job.reduces = 5;

    • join(空KEY轉(zhuǎn)化)

        insert overwrite table jointable
        select
            n.*
        from
            nullidtable n 
        full join ori o
        on case when n.id is null then concat('hive', rand()) else n.id end = o.id;
      

3. MapJoin

  • 概念

    • 如果不指定 MapJoin 或者不符合 MapJoin 的條件,那么 Hive 解析器會(huì)將 Join 操作轉(zhuǎn)換,成 Common Join

    • 即:在 Reduce 階段完成 join。容易發(fā)生數(shù)據(jù)傾斜??梢杂?MapJoin 把小表全部加載到內(nèi)存在 map 端進(jìn)行 join,避免 reducer 處理。

  • 參數(shù)設(shè)置

    • hive.auto.convert.join 設(shè)置mapjoin打開關(guān)閉;默認(rèn)為true
    • hive.mapjoin.smalltable.filesize 設(shè)置小表閾值,默認(rèn)為25000000;25M
  • 深入理解

    • 當(dāng)滿足mapjoin條件時(shí),會(huì)自動(dòng)更改為mapJoin

    • 也可以手動(dòng)指定為MapJoin

    • But the mapjoin hint should only be used for the following query

      • if all the inputs are bucketed or sorted,and the join should be converted to a bucketed map-side join or bucketized sort-merge join.

      • 當(dāng)兩張join的表根據(jù)同一列進(jìn)行分桶,且表的分桶數(shù)相同或者成倍數(shù),則兩表連接時(shí)會(huì)對應(yīng)join

          select /* + MAPJOIN(b)*/ a.key,a.value from a join b on a.key = b.key
        
        • join can be done on the mapper only

        • Instead of fetching B completely for each mapper of A,only the required buckets are fetched.

        • the mapper processing bucket 1 for A will only fetch bucket 1 of B

        • 需要設(shè)置屬性:set hive.optimize.bucketmapjoin = true;

      • 當(dāng)兩張join的表根據(jù)同一列進(jìn)行分桶且桶內(nèi)根據(jù)此列有序,且表的分桶數(shù)相同,a sort-merge join can be performed. The corresponding buckets are joined with each other at the mapper.

4. Group By

  • 概念

    • 默認(rèn)情況下,Map 階段同一 Key 數(shù)據(jù)分發(fā)給一個(gè) reduce,當(dāng)一個(gè) key 數(shù)據(jù)過大時(shí)就傾斜了。

    • 并不是所有的聚合操作都需要在 Reduce 端完成,很多聚合操作都可以先在 Map 端進(jìn)行部分聚合,最后在 Reduce 端得出最終結(jié)果。

    • 可對應(yīng)于hadoop的MapReduce中的combine操作,與reduce實(shí)現(xiàn)相同業(yè)務(wù)邏輯,運(yùn)行每一個(gè)map task中,減輕shuffle中從map到reduce的傳輸。

    • 不是所有的聚合都需要進(jìn)行此項(xiàng)優(yōu)化。當(dāng)group by 的字段沒有相同的時(shí),則無效

      • select * from emp group by empno;

      • 因?yàn)閑mpno沒有重復(fù)的,因此map聚合沒有太大意義,并且浪費(fèi)資源。

  • 參數(shù)設(shè)置

    • 是否在 Map 端進(jìn)行聚合,默認(rèn)為 True

        hive.map.aggr = true
      
    • 在 Map 端進(jìn)行聚合操作的條目數(shù)目

        hive.groupby.mapaggr.checkinterval = 100000
      
    • 有數(shù)據(jù)傾斜的時(shí)候進(jìn)行負(fù)載均衡(默認(rèn)是 false)

        hive.groupby.skewindata = true
      
        * 當(dāng)選項(xiàng)設(shè)定為 true,生成的查詢計(jì)劃會(huì)有兩個(gè) MR Job。
        
        * 第一個(gè) MR Job 中,Map 的輸出結(jié)果會(huì)隨機(jī)分布到 Reduce 中,每個(gè) Reduce 做部分聚合操作,并輸出結(jié)果,這樣處理的結(jié)果是相同的 Group By Key 有可能被分發(fā)到不同的 Reduce 中,從而達(dá)到負(fù)載均衡的目的;、
        
        * 第二個(gè) MR Job 再根據(jù)預(yù)處理的數(shù)據(jù)結(jié)果按照 Group By Key 分布到 Reduce 中(這個(gè)過程可以保證相同的 Group By Key 被分布到同一個(gè) Reduce 中),最后完成最終的聚合操作。
      

5. count(distinct) 去重統(tǒng)計(jì)

  • 概念

    • 數(shù)據(jù)量小的時(shí)候無所謂,數(shù)據(jù)量大的情況下,由于 COUNT DISTINCT 操作需要用一個(gè)Reduce Task 來完成,這一個(gè) Reduce 需要處理的數(shù)據(jù)量太大,就會(huì)導(dǎo)致整個(gè) Job 很難完成,

    • 一般 COUNT DISTINCT 使用先 GROUP BY 再 COUNT 的方式替換:

  • 參數(shù)設(shè)置

    • set mapreduce.job.reduces = xxxx; 對reduce個(gè)數(shù)進(jìn)行設(shè)置

        select 
            count(id)
        from (
            select 
                id
            from
                bigtable
            group by
                id) a;
      
    • 先根據(jù)id進(jìn)行部分聚合,然后統(tǒng)計(jì)個(gè)數(shù)

6. 笛卡爾積

* 盡量避免笛卡爾積,join 的時(shí)候不加 on 條件,或者無效的 on 條件,Hive 只能使用 1個(gè) reducer 來完成笛卡爾積

7. 行列過濾

  • 列處理:

    • 在 SELECT 中,只拿需要的列,如果有,盡量使用分區(qū)過濾,少用 SELECT *。
  • 行處理:

    • 在分區(qū)剪裁中,當(dāng)使用外關(guān)聯(lián)時(shí),如果將副表的過濾條件寫在 Where 后面那么就會(huì)先全表關(guān)聯(lián),之后再過濾,應(yīng)該通過子查詢后,再關(guān)聯(lián)表

        select 
            b.id
        from
            bigtable b
        join (
            select
                id
            from
                ori 
            where id <= 10 ) o 
        on b.id = o.id;
      

8. 動(dòng)態(tài)分區(qū)調(diào)整

  • 概念

    • 關(guān)系型數(shù)據(jù)庫中,對分區(qū)表 Insert 數(shù)據(jù)時(shí)候,數(shù)據(jù)庫自動(dòng)會(huì)根據(jù)分區(qū)字段的值,將數(shù)據(jù)插入到相應(yīng)的分區(qū)中

    • Hive 中也提供了類似的機(jī)制,即動(dòng)態(tài)分區(qū)(Dynamic Partition),只不過,使用 Hive 的動(dòng)態(tài)分區(qū),需要進(jìn)行相應(yīng)的配置。

  • 參數(shù)設(shè)置

    • 開啟動(dòng)態(tài)分區(qū)功能(默認(rèn) true,開啟)

        hive.exec.dynamic.partition=true
      
    • 設(shè)置為非嚴(yán)格模式(動(dòng)態(tài)分區(qū)的模式,默認(rèn) strict,表示必須指定至少一個(gè)分區(qū)為靜態(tài)分區(qū),nonstrict 模式表示允許所有的分區(qū)字段都可以使用動(dòng)態(tài)分區(qū)。)

        hive.exec.dynamic.partition.mode=nonstrict
      
    • 在所有執(zhí)行 MR 的節(jié)點(diǎn)上,最大一共可以創(chuàng)建多少個(gè)動(dòng)態(tài)分區(qū)。

        hive.exec.max.dynamic.partitions=1000
      
    • 在每個(gè)執(zhí)行 MR 的節(jié)點(diǎn)上,最大可以創(chuàng)建多少個(gè)動(dòng)態(tài)分區(qū)。該參數(shù)需要根據(jù)實(shí)際的數(shù)據(jù)來設(shè)定。比如:源數(shù)據(jù)中包含了一年的數(shù)據(jù),即 day 字段有 365 個(gè)值,那么該參數(shù)就需要設(shè)置成大于 365,如果使用默認(rèn)值 100,則會(huì)報(bào)錯(cuò)。

        hive.exec.max.dynamic.partitions.pernode=100
      
    • 整個(gè) MR Job 中,最大可以創(chuàng)建多少個(gè) HDFS 文件。

        hive.exec.max.created.files=100000
      
    • 當(dāng)有空分區(qū)生成時(shí),是否拋出異常。一般不需要設(shè)置。

        hive.error.on.empty.partition=false
      
  • 操作

      insert overwrite table ori_partitioned_target
      partition (p_time)                              //指定分區(qū)列
      select
          id, time, uid, keyword, url_rank, click_num, click_url, p_time          //分區(qū)列也要作為一個(gè)字段查出
      from
          ori_partitioned;
    

9. 分區(qū)

  • 分區(qū)的理解:

    • 分區(qū)是一種根據(jù)“分區(qū)列”的值對表進(jìn)行粗略劃分的機(jī)制

    • Hive中的每個(gè)分區(qū)對應(yīng)著數(shù)據(jù)庫中相應(yīng)分區(qū)列的一個(gè)索引;

      • 每個(gè)分區(qū)對應(yīng)著表下的一個(gè)目錄

      • 分區(qū)在HDFS上的表現(xiàn)形式與表在 HDFS上的表現(xiàn)形式相同,都是以子目錄的形式存在

    • 查詢時(shí)通過where選擇查詢的指定分區(qū),可提高查詢效率。

      • 當(dāng)只需要遍歷小范圍內(nèi)的數(shù)據(jù)時(shí)或一定條件下的數(shù)據(jù),可有效減少掃描數(shù)據(jù)的數(shù)量
    • 一個(gè)表可在多個(gè)維度上進(jìn)行分區(qū),且分區(qū)可以嵌套使用,建表時(shí)通過partitioned by 來創(chuàng)建分區(qū)

      • partitioned by (year string)

      • partitioned by (year string,month string)

    • 將分區(qū)加載到表內(nèi)之前,需要指定添加分區(qū)列,否則報(bào)錯(cuò)。

      • 此時(shí)聯(lián)系到動(dòng)分區(qū)的調(diào)整

      • 動(dòng)態(tài)分區(qū)需要:

        ①開啟動(dòng)態(tài)分區(qū)

          hive.exec.dynamic.partition=true
        

        ②設(shè)置為非嚴(yán)格模式

          hive.exec.dynamic.partition.mode=nonstrict
        
    • partitioned by 子句中的列是表中正式的列(分區(qū)列,通過select * 可查到),但是表數(shù)據(jù)中并不包含這些列

10. 分桶

  • 分桶的理解

    • 桶為表提供了額外的結(jié)構(gòu),hive在處理某些查詢時(shí)利用這個(gè)結(jié)構(gòu),能提高查詢效率

    • 桶通過對指定列進(jìn)行哈希計(jì)算來實(shí)現(xiàn)的,通過對哈希值將一個(gè)列名下的數(shù)據(jù)切分為一組桶,并使每個(gè)桶對應(yīng)于該列名下的存儲文件

    • 建立桶之前,需要設(shè)置hive.enforce.bucketing = true;

    • 分區(qū)和分桶其中一個(gè)區(qū)別在于

      • 分區(qū)中的指定列在表數(shù)據(jù)中不存在,即數(shù)據(jù)文件中不存在

      • 分桶中的指定列在表數(shù)據(jù)中存在

    • 向桶中插入數(shù)據(jù),若分為4個(gè)桶,則在插入數(shù)據(jù)時(shí),對應(yīng)于4個(gè)reduce操作,輸出4個(gè)文件

  • 分區(qū)中的分桶

    • 注意分區(qū)中分桶的數(shù)據(jù)插入

    • clustered by (id) sorted by (age) into 4 buckets

      • clustered by 和 sorted by 不會(huì)影響數(shù)據(jù)的導(dǎo)入,插入的數(shù)據(jù)若需要排序,則需要手動(dòng)定義

11. left semi join

  • 概念

    • left semi join是對in/exists子查詢提供了更高效的方式

    • 下面兩個(gè)語句等價(jià)

        select 
            a.key,a.value
        from
            a
        where
            a.key in(
            select b.key from B);
      
        等價(jià)于
      
        select
            a.key,a.value
        from
            a
        left semi join b
        on (a.key = b.key)
      
    • The restrictions of using left semi join are that the right-side join table should only be referened in the join condition, but not in where or select clause etc.(left semi join中右邊的表只能在on 中被引用,不可在where,select中等使用)

12. insert into 代替 union all

  • 不同表的union all相當(dāng)于multiple inputs,同一個(gè)表的union all,相當(dāng)map一次輸出多條。

  • 如果union all的部分個(gè)數(shù)大于2,或者每個(gè)union部分?jǐn)?shù)據(jù)量大,應(yīng)該拆成多個(gè)insert into 語句,實(shí)際測試過程中,執(zhí)行時(shí)間能提升50%

      insert overwite table tablename partition (dt= ....)    
      select ..... from ( select ... from A       
      union all       
      select ... from B  union all select ... from C ) R      
      where ...;
      
      可以改寫為:
      
      insert into table tablename partition (dt= ....) select .... from A WHERE ...;
      
      insert into table tablename partition (dt= ....) select .... from B  WHERE ...;
      
      insert into table tablename partition (dt= ....) select .... from C WHERE ...;
    

四、數(shù)據(jù)傾斜

概述

  • 數(shù)據(jù)傾斜表現(xiàn):

    • 任務(wù)進(jìn)度長時(shí)間維持在99%(或100%),查看任務(wù)監(jiān)控頁面,發(fā)現(xiàn)只有少量(1個(gè)或幾個(gè))reduce子任務(wù)未完成。因?yàn)槠涮幚淼臄?shù)據(jù)量和其他reduce差異過大。
  • 數(shù)據(jù)傾斜原因:

    • key分布不均勻

    • 業(yè)務(wù)數(shù)據(jù)本身的特性

    • 建表時(shí)考慮不周

    • 某些SQL語句本身就有數(shù)據(jù)傾斜

           關(guān)鍵詞                  情形                                          后果
            -----------------|----------------------------------------------|--------------------------------------------------
            join                其中一個(gè)表較小,但是key集中                     分發(fā)到某一個(gè)或幾個(gè)Reduce上的數(shù)據(jù)遠(yuǎn)高于平均值
            -----------------|----------------------------------------------|-------------------------------------------------
            join                大表與大表,但是分桶的判斷字段0值或空值過多          這些空值都由一個(gè)reduce處理,非常慢
            -----------------|----------------------------------------------|------------------------------------------------
            group by            group by 維度過小,某值的數(shù)量過多                   處理某值的reduce非常耗時(shí)
            -----------------|----------------------------------------------|-------------------------------------------------
            count distinct      某特殊值過多                                      處理此特殊值reduce耗時(shí)
            -----------------|----------------------------------------------|-------------------------------------------------
      

1. 合理設(shè)置map數(shù)量

  • 概念

    • 通常情況下,作業(yè)會(huì)通過 input 的目錄產(chǎn)生一個(gè)或者多個(gè) map 任務(wù)

      • 主要的決定因素有:input 的文件總個(gè)數(shù),input 的文件大小,集群設(shè)置的文件塊大小。

      • 涉及到split切片機(jī)制

        • size = Math.max(minSize,Math.min(maxSize,blockSize));
      • 如果集群性能好的話,可設(shè)置blockSize

      • 開啟map端的聚合

    • 也可以適當(dāng)調(diào)整環(huán)形緩沖區(qū)的大小以提高效率

2. 小文件進(jìn)行合并

  • 在 map 執(zhí)行前合并小文件,減少 map 數(shù):

    • CombineHiveInputFormat 具有對小文件進(jìn)行合并的功能(系統(tǒng)默認(rèn)的格式)。

    • HiveInputFormat 沒有對小文件合并功能。

        set hive.input.format= org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
      

3. 復(fù)雜文件增加 Map 數(shù)

  • 當(dāng) input 的文件都很大,任務(wù)邏輯復(fù)雜,map 執(zhí)行非常慢的時(shí)候,可以考慮增加 Map數(shù),來使得每個(gè) map 處理的數(shù)據(jù)量減少,從而提高任務(wù)的執(zhí)行效率。

  • 增加 map 的方法為:根據(jù)

      computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M 公式
    
  • 調(diào)整 maxSize 最大值。讓 maxSize 最大值低于 blocksize 就可以增加 map 的個(gè)數(shù)。

4. 合理設(shè)置 Reduce 數(shù)

4.1 調(diào)整 reduce 個(gè)數(shù)方法一

  • 每個(gè) Reduce 處理的數(shù)據(jù)量默認(rèn)是 256MB

      hive.exec.reducers.bytes.per.reducer=256000000
    
  • 每個(gè)任務(wù)最大的 reduce 數(shù),默認(rèn)為 1009

      hive.exec.reducers.max=1009
    
  • 計(jì)算 reducer 數(shù)的公式

      N=min(參數(shù) 2,總輸入數(shù)據(jù)量/參數(shù) 1)
    

4.2 調(diào)整 reduce 個(gè)數(shù)方法二

  • 在 hadoop 的 mapred-default.xml 文件中修改

      設(shè)置每個(gè) job 的 Reduce 個(gè)數(shù)
      set mapreduce.job.reduces = 15;
    
  • 具體的個(gè)數(shù)需要經(jīng)過測試來得知

五、并行執(zhí)行

  • 概念

    • Hive 會(huì)將一個(gè)查詢轉(zhuǎn)化成一個(gè)或者多個(gè)階段。這樣的階段可以是 MapReduce 階段、抽樣階段、合并階段、limit 階段。或者 Hive 執(zhí)行過程中可能需要的其他階段。

    • 默認(rèn)情況下,Hive 一次只會(huì)執(zhí)行一個(gè)階段。

    • 不過,如果某些階段不是互相依賴,是可以并行執(zhí)行的。

  • 參數(shù)設(shè)置

      set hive.exec.parallel=true; //打開任務(wù)并行執(zhí)行
      set hive.exec.parallel.thread.number=16; //同一個(gè) sql 允許最大并行度,默認(rèn)為 8。
    
  • 不過,在共享集群中,需要注意下,如果 job 中并行階段增多,那么集群利用率就會(huì)增加。當(dāng)然,得是在系統(tǒng)資源比較空閑的時(shí)候才有優(yōu)勢,否則,沒資源,并行也起不來

六、嚴(yán)格模式

開啟嚴(yán)格模式可以禁止 3 種類型的查詢。

1. 分區(qū)表——where過濾

  • 對于分區(qū)表,除非 where 語句中含有分區(qū)字段過濾條件來限制范圍,否則不允許執(zhí)行。

  • 就是用戶不允許掃描所有分區(qū)。進(jìn)行這個(gè)限制的原因是,通常分區(qū)表都擁有非常大的數(shù)據(jù)集,而且數(shù)據(jù)增加迅速。沒有進(jìn)行分區(qū)限制的查詢可能會(huì)消耗令人不可接受的巨大資源來處理這個(gè)表。

2. order by 搭配limit使用

  • 對于使用了 order by 語句的查詢,要求必須使用 limit 語句。

  • 因?yàn)?order by 為了執(zhí)行排序過程會(huì)將所有的結(jié)果數(shù)據(jù)分發(fā)到同一個(gè) Reducer 中進(jìn)行處理,強(qiáng)制要求用戶增加這個(gè) LIMIT語句可以防止 Reducer 額外執(zhí)行很長一段時(shí)間。

3. 限制笛卡爾積的查詢。

  • 多表join時(shí),指定join條件

七、JVM重用(針對同一個(gè)job的tasks而言的)

  • 概念

    • JVM 重用是 Hadoop 調(diào)優(yōu)參數(shù)的內(nèi)容,其對 Hive 的性能具有非常大的影響,特別是對于很難避免小文件的場景或 task 特別多的場景,這類場景大多數(shù)執(zhí)行時(shí)間都很短。

    • Hadoop中有個(gè)參數(shù)是mapred.job.reuse.jvm.num.tasks,默認(rèn)是1,表示一個(gè)JVM上最多可以順序執(zhí)行的task數(shù)目(屬于同一個(gè)Job)是1。也就是說一個(gè)task啟一個(gè)JVM。

    • 為每個(gè)task啟動(dòng)一個(gè)新的JVM將耗時(shí)1秒左右,對于運(yùn)行時(shí)間較長(比如1分鐘以上)的job影響不大,但如果都是時(shí)間很短的task,那么頻繁啟停JVM會(huì)有開銷。

  • 參數(shù)設(shè)置

    • 如果我們想使用JVM重用技術(shù)來提高性能,那么可以將mapred.job.reuse.jvm.num.tasks設(shè)置成大于1的數(shù)。這表示屬于同一job的順序執(zhí)行的task可以共享一個(gè)JVM,也就是說第二輪的map可以重用前一輪的JVM,而不是第一輪結(jié)束后關(guān)閉JVM,第二輪再啟動(dòng)新的JVM。

    • 那么最多一個(gè)JVM能順序執(zhí)行多少個(gè)task才關(guān)閉呢?

      • 這個(gè)值就是mapred.job.reuse.jvm.num.tasks。如果設(shè)置成-1,那么只要是同一個(gè)job的task(無所謂多少個(gè)),都可以按順序在一個(gè)JVM上連續(xù)執(zhí)行
    • 如果task屬于不同的job,那么JVM重用機(jī)制無效,不同job的task需要不同的JVM來運(yùn)行

  • 注意事項(xiàng)

    • JVM重用技術(shù)不是指同一Job的兩個(gè)或兩個(gè)以上的task可以同時(shí)運(yùn)行于同一JVM上,而是排隊(duì)按順序執(zhí)行。

    • 一個(gè)tasktracker最多可以同時(shí)運(yùn)行的task數(shù)目由mapred.tasktracker.map.tasks.maximum和mapred.tasktracker.reduce.tasks.maximum決定,并且這兩個(gè)參數(shù)在mapred-site.xml中設(shè)置。

    • 其他方法,如在JobClient端通過命令行-Dmapred.tasktracker.map.tasks.maximum=number或者conf.set("mapred.tasktracker.map.tasks.maximum","number")設(shè)置都是無效的。

    • 這個(gè)功能的缺點(diǎn)是,開啟 JVM 重用將一直占用使用到的 task 插槽,以便進(jìn)行重用,直到任務(wù)完成后才能釋放。如果某個(gè)“不平衡的”job 中有某幾個(gè) reduce task 執(zhí)行的時(shí)間要比其他 Reduce task 消耗的時(shí)間多的多的話,那么保留的插槽就會(huì)一直空閑著卻無法被其他的 job使用,直到所有的 task 都結(jié)束了才會(huì)釋放。

八、推測執(zhí)行

  • 概念

    • 在分布式集群環(huán)境下,因?yàn)槌绦?Bug(包括 Hadoop 本身的 bug),負(fù)載不均衡或者資源分布不均等原因,會(huì)造成同一個(gè)作業(yè)的多個(gè)任務(wù)之間運(yùn)行速度不一致,有些任務(wù)的運(yùn)行速度可能明顯慢于其他任務(wù)(比如一個(gè)作業(yè)的某個(gè)任務(wù)進(jìn)度只有 50%,而其他所有任務(wù)已經(jīng)運(yùn)行完畢),則這些任務(wù)會(huì)拖慢作業(yè)的整體執(zhí)行進(jìn)度。

    • 為了避免這種情況發(fā)生,Hadoop 采用了推測執(zhí)行(Speculative Execution)機(jī)制,它根據(jù)一定的法則推測出“拖后腿”的任務(wù),并為這樣的任務(wù)啟動(dòng)一個(gè)備份任務(wù),讓該任務(wù)與原始任務(wù)同時(shí)處理同一份數(shù)據(jù),并最終選用最先成功運(yùn)行完成任務(wù)的計(jì)算結(jié)果作為最終結(jié)果。

  • 參數(shù)設(shè)置

      <property>
           <name>mapreduce.map.speculative</name>
           <value>true</value>
           <description>If true, then multiple instances of some map tasks may be executed in parallel.</description>
      </property>
      
      <property>
           <name>mapreduce.reduce.speculative</name>
           <value>true</value>
           <description>If true, then multiple instances of some reduce tasks  may be executed in parallel.</description>
      </property>
    
      <property>
           <name>hive.mapred.reduce.tasks.speculative.execution</name>
           <value>true</value>
           <description>Whether speculative execution for reducers should be turned on.</description>
       </property>
    
  • 注意事項(xiàng)

    • 如果用戶因?yàn)檩斎霐?shù)據(jù)量很大而需要執(zhí)行長時(shí)間的 map 或者 Reduce task 的話,那么啟動(dòng)推測執(zhí)行造成的浪費(fèi)是非常巨大大。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,725評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,695評論 2 370

推薦閱讀更多精彩內(nèi)容