1. Hive企業(yè)級(jí)性能優(yōu)化(建議收藏)

        共 7203字,需瀏覽 15分鐘

         ·

        2021-04-14 11:55

        點(diǎn)擊上方 "大數(shù)據(jù)肌肉猿"關(guān)注, 星標(biāo)一起成長(zhǎng)

        后臺(tái)回復(fù)【加群】,進(jìn)入高質(zhì)量學(xué)習(xí)交流群

        2021年大數(shù)據(jù)肌肉猿公眾號(hào)獎(jiǎng)勵(lì)制度

        Hive作為大數(shù)據(jù)平臺(tái)舉足輕重的框架,以其穩(wěn)定性和簡(jiǎn)單易用性也成為當(dāng)前構(gòu)建企業(yè)級(jí)數(shù)據(jù)倉(cāng)庫(kù)時(shí)使用最多的框架之一。

        但是如果我們只局限于會(huì)使用Hive,而不考慮性能問(wèn)題,就難搭建出一個(gè)完美的數(shù)倉(cāng),所以Hive性能調(diào)優(yōu)是我們大數(shù)據(jù)從業(yè)者必須掌握的技能。本文將給大家講解Hive性能調(diào)優(yōu)的一些方法及技巧。

        Hive性能問(wèn)題排查方式

        當(dāng)我們發(fā)現(xiàn)一條SQL語(yǔ)句執(zhí)行時(shí)間過(guò)長(zhǎng)或者不合理時(shí),我們就要考慮對(duì)SQL進(jìn)行優(yōu)化,優(yōu)化首先得進(jìn)行問(wèn)題排查,那么我們可以通過(guò)哪些方式進(jìn)行排查呢。

        經(jīng)常使用關(guān)系型數(shù)據(jù)庫(kù)的同學(xué)可能知道關(guān)系型數(shù)據(jù)庫(kù)的優(yōu)化的訣竅-看執(zhí)行計(jì)劃。如Oracle數(shù)據(jù)庫(kù),它有多種類(lèi)型的執(zhí)行計(jì)劃,通過(guò)多種執(zhí)行計(jì)劃的配合使用,可以看到根據(jù)統(tǒng)計(jì)信息推演的執(zhí)行計(jì)劃,即Oracle推斷出來(lái)的未真正運(yùn)行的執(zhí)行計(jì)劃;能夠觀察到從數(shù)據(jù)讀取到最終呈現(xiàn)的主要過(guò)程和中間的量化數(shù)據(jù)??梢哉f(shuō),在Oracle開(kāi)發(fā)領(lǐng)域,掌握合適的環(huán)節(jié),選用不同的執(zhí)行計(jì)劃,SQL調(diào)優(yōu)就不是一件難事。

        Hive中也有執(zhí)行計(jì)劃,但是Hive的執(zhí)行計(jì)劃都是預(yù)測(cè)的,這點(diǎn)不像Oracle和SQL Server有真實(shí)的計(jì)劃,可以看到每個(gè)階段的處理數(shù)據(jù)、消耗的資源和處理的時(shí)間等量化數(shù)據(jù)。Hive提供的執(zhí)行計(jì)劃沒(méi)有這些數(shù)據(jù),這意味著雖然Hive的使用者知道整個(gè)SQL的執(zhí)行邏輯,但是各階段耗用的資源狀況和整個(gè)SQL的執(zhí)行瓶頸在哪里是不清楚的。

        想要知道HiveSQL所有階段的運(yùn)行信息,可以查看YARN提供的日志。查看日志的鏈接,可以在每個(gè)作業(yè)執(zhí)行后,在控制臺(tái)打印的信息中找到。如下圖所示:

        Hive提供的執(zhí)行計(jì)劃目前可以查看的信息有以下幾種

        1. 查看執(zhí)行計(jì)劃的基本信息,即explain;
        2. 查看執(zhí)行計(jì)劃的擴(kuò)展信息,即explain extended;
        3. 查看SQL數(shù)據(jù)輸入依賴(lài)的信息,即explain dependency;
        4. 查看SQL操作相關(guān)權(quán)限的信息,即explain authorization;
        5. 查看SQL的向量化描述信息,即explain vectorization。

        在查詢(xún)語(yǔ)句的SQL前面加上關(guān)鍵字explain是查看執(zhí)行計(jì)劃的基本方法。用explain打開(kāi)的執(zhí)行計(jì)劃包含以下兩部分:

        • 作業(yè)的依賴(lài)關(guān)系圖,即STAGE DEPENDENCIES;
        • 每個(gè)作業(yè)的詳細(xì)信息,即STAGE PLANS。

        Hive中的explain執(zhí)行計(jì)劃詳解可看我之前寫(xiě)的這篇文章Hive底層原理:explain執(zhí)行計(jì)劃詳解

        注:使用explain查看執(zhí)行計(jì)劃是Hive性能調(diào)優(yōu)中非常重要的一種方式,請(qǐng)務(wù)必掌握!

        總結(jié):Hive對(duì)SQL語(yǔ)句性能問(wèn)題排查的方式

        1. 使用explain查看執(zhí)行計(jì)劃;
        2. 查看YARN提供的日志。

        Hive性能調(diào)優(yōu)的方式

        為什么都說(shuō)性能優(yōu)化這項(xiàng)工作是比較難的,因?yàn)橐豁?xiàng)技術(shù)的優(yōu)化,必然是一項(xiàng)綜合性的工作,它是多門(mén)技術(shù)的結(jié)合。我們?nèi)绻痪窒抻谝环N技術(shù),那么肯定做不好優(yōu)化的。

        下面將從多個(gè)完全不同的角度來(lái)介紹Hive優(yōu)化的多樣性,我們先來(lái)一起感受下。

        1. SQL語(yǔ)句優(yōu)化

        SQL語(yǔ)句優(yōu)化涉及到的內(nèi)容太多,因篇幅有限,不能一一介紹到,所以就拿幾個(gè)典型舉例,讓大家學(xué)到這種思想,以后遇到類(lèi)似調(diào)優(yōu)問(wèn)題可以往這幾個(gè)方面多思考下。

        1. union all


        insert into table stu partition(tp) 
        select s_age,max(s_birth) stat,'max' tp 
        from stu_ori
        group by s_age

        union all

        insert into table stu partition(tp) 
        select s_age,min(s_birth) stat,'min' tp 
        from stu_ori
        group by s_age;

        我們簡(jiǎn)單分析上面的SQL語(yǔ)句,就是將每個(gè)年齡段的最大和最小的生日獲取出來(lái)放到同一張表中,union all 前后的兩個(gè)語(yǔ)句都是對(duì)同一張表按照s_age進(jìn)行分組,然后分別取最大值和最小值。

        上面的SQL對(duì)同一張表相同字段進(jìn)行兩次分組,這顯然造成了極大浪費(fèi),我們能不能改造下呢,當(dāng)然是可以的,為大家介紹一個(gè)語(yǔ)法: from ... insert into ... ,這個(gè)語(yǔ)法將from前置,作用就是使用一張表,可以進(jìn)行多次插入操作:

        --開(kāi)啟動(dòng)態(tài)分區(qū) 
        set hive.exec.dynamic.partition=true
        set hive.exec.dynamic.partition.mode=nonstrict; 

        from stu_ori 

        insert into table stu partition(tp) 
        select s_age,max(s_birth) stat,'max' tp 
        group by s_age

        insert into table stu partition(tp) 
        select s_age,min(s_birth) stat,'min' tp 
        group by s_age;

        上面的SQL就可以對(duì)stu_ori表的s_age字段分組一次而進(jìn)行兩次不同的插入操作。

        這個(gè)例子告訴我們一定要多了解SQL語(yǔ)句,如果我們不知道這種語(yǔ)法,一定不會(huì)想到這種方式的

        2. distinct

        先看一個(gè)SQL,去重計(jì)數(shù):

        select count(1
        from
          select s_age 
          from stu 
          group by s_age 
        ) b;

        這是簡(jiǎn)單統(tǒng)計(jì)年齡的枚舉值個(gè)數(shù),為什么不用distinct?

        select count(distinct s_age) 
        from stu;

        有人說(shuō)因?yàn)樵跀?shù)據(jù)量特別大的情況下使用第一種方式(group by)能夠有效避免Reduce端的數(shù)據(jù)傾斜,但事實(shí)如此嗎?

        我們先不管數(shù)據(jù)量特別大這個(gè)問(wèn)題,就當(dāng)前的業(yè)務(wù)和環(huán)境下使用distinct一定會(huì)比上面那種子查詢(xún)的方式效率高。原因有以下幾點(diǎn):

        1. 上面進(jìn)行去重的字段是年齡字段,要知道年齡的枚舉值是非常有限的,就算計(jì)算1歲到100歲之間的年齡,s_age的最大枚舉值才100,如果轉(zhuǎn)化成MapReduce來(lái)解釋的話,在Map階段,每個(gè)Map會(huì)對(duì)s_age去重。由于s_age枚舉值有限,因而每個(gè)Map得到的s_age也有限,最終得到reduce的數(shù)據(jù)量也就是map數(shù)量*s_age枚舉值的個(gè)數(shù)。這個(gè)數(shù)量是很小的。

        2. distinct的命令會(huì)在內(nèi)存中構(gòu)建一個(gè)hashtable,查找去重的時(shí)間復(fù)雜度是O(1);group by在不同版本間變動(dòng)比較大,有的版本會(huì)用構(gòu)建hashtable的形式去重,有的版本會(huì)通過(guò)排序的方式, 排序最優(yōu)時(shí)間復(fù)雜度無(wú)法到O(1)。另外,第一種方式(group by)去重會(huì)轉(zhuǎn)化為兩個(gè)任務(wù),會(huì)消耗更多的磁盤(pán)網(wǎng)絡(luò)I/O資源。

        3. 最新的Hive 3.0中新增了 count(distinct) 優(yōu)化,通過(guò)配置 hive.optimize.countdistinct,即使真的出現(xiàn)數(shù)據(jù)傾斜也可以自動(dòng)優(yōu)化,自動(dòng)改變SQL執(zhí)行的邏輯。

        4. 第二種方式(distinct)比第一種方式(group by)代碼簡(jiǎn)潔,表達(dá)的意思簡(jiǎn)單明了,如果沒(méi)有特殊的問(wèn)題,代碼簡(jiǎn)潔就是優(yōu)!

        這個(gè)例子告訴我們,有時(shí)候我們不要過(guò)度優(yōu)化,調(diào)優(yōu)講究適時(shí)調(diào)優(yōu),過(guò)早進(jìn)行調(diào)優(yōu)有可能做的是無(wú)用功甚至產(chǎn)生負(fù)效應(yīng),在調(diào)優(yōu)上投入的工作成本和回報(bào)不成正比。調(diào)優(yōu)需要遵循一定的原則

        2. 數(shù)據(jù)格式優(yōu)化

        Hive提供了多種數(shù)據(jù)存儲(chǔ)組織格式,不同格式對(duì)程序的運(yùn)行效率也會(huì)有極大的影響。

        Hive提供的格式有TEXT、SequenceFile、RCFile、ORC和Parquet等。

        SequenceFile是一個(gè)二進(jìn)制key/value對(duì)結(jié)構(gòu)的平面文件,在早期的Hadoop平臺(tái)上被廣泛用于MapReduce輸出/輸出格式,以及作為數(shù)據(jù)存儲(chǔ)格式。

        Parquet是一種列式數(shù)據(jù)存儲(chǔ)格式,可以兼容多種計(jì)算引擎,如MapRedcue和Spark等,對(duì)多層嵌套的數(shù)據(jù)結(jié)構(gòu)提供了良好的性能支持,是目前Hive生產(chǎn)環(huán)境中數(shù)據(jù)存儲(chǔ)的主流選擇之一。

        ORC優(yōu)化是對(duì)RCFile的一種優(yōu)化,它提供了一種高效的方式來(lái)存儲(chǔ)Hive數(shù)據(jù),同時(shí)也能夠提高Hive的讀取、寫(xiě)入和處理數(shù)據(jù)的性能,能夠兼容多種計(jì)算引擎。事實(shí)上,在實(shí)際的生產(chǎn)環(huán)境中,ORC已經(jīng)成為了Hive在數(shù)據(jù)存儲(chǔ)上的主流選擇之一。

        我們執(zhí)行同樣的SQL語(yǔ)句及同樣的數(shù)據(jù),只是數(shù)據(jù)存儲(chǔ)格式不同,得到如下執(zhí)行時(shí)長(zhǎng):

        數(shù)據(jù)格式CPU時(shí)間用戶(hù)等待耗時(shí)
        TextFile33分171秒
        SequenceFile38分162秒
        Parquet2分22秒50秒
        ORC1分52秒56秒

        注:CPU時(shí)間:表示運(yùn)行程序所占用服務(wù)器CPU資源的時(shí)間。
        用戶(hù)等待耗時(shí):記錄的是用戶(hù)從提交作業(yè)到返回結(jié)果期間用戶(hù)等待的所有時(shí)間。

        查詢(xún)TextFile類(lèi)型的數(shù)據(jù)表耗時(shí)33分鐘, 查詢(xún)ORC類(lèi)型的表耗時(shí)1分52秒,時(shí)間得以極大縮短,可見(jiàn)不同的數(shù)據(jù)存儲(chǔ)格式也能給HiveSQL性能帶來(lái)極大的影響。

        3. 小文件過(guò)多優(yōu)化

        小文件如果過(guò)多,對(duì) hive 來(lái)說(shuō),在進(jìn)行查詢(xún)時(shí),每個(gè)小文件都會(huì)當(dāng)成一個(gè)塊,啟動(dòng)一個(gè)Map任務(wù)來(lái)完成,而一個(gè)Map任務(wù)啟動(dòng)和初始化的時(shí)間遠(yuǎn)遠(yuǎn)大于邏輯處理的時(shí)間,就會(huì)造成很大的資源浪費(fèi)。而且,同時(shí)可執(zhí)行的Map數(shù)量是受限的。

        所以我們有必要對(duì)小文件過(guò)多進(jìn)行優(yōu)化,關(guān)于小文件過(guò)多的解決的辦法,我之前專(zhuān)門(mén)寫(xiě)了一篇文章講解,具體可查看:解決hive小文件過(guò)多問(wèn)題

        4. 并行執(zhí)行優(yōu)化

        Hive會(huì)將一個(gè)查詢(xún)轉(zhuǎn)化成一個(gè)或者多個(gè)階段。這樣的階段可以是MapReduce階段、抽樣階段、合并階段、limit階段。或者Hive執(zhí)行過(guò)程中可能需要的其他階段。默認(rèn)情況下,Hive一次只會(huì)執(zhí)行一個(gè)階段。不過(guò),某個(gè)特定的job可能包含眾多的階段,而這些階段可能并非完全互相依賴(lài)的,也就是說(shuō)有些階段是可以并行執(zhí)行的,這樣可能使得整個(gè)job的執(zhí)行時(shí)間縮短。如果有更多的階段可以并行執(zhí)行,那么job可能就越快完成。

        通過(guò)設(shè)置參數(shù)hive.exec.parallel值為true,就可以開(kāi)啟并發(fā)執(zhí)行。在共享集群中,需要注意下,如果job中并行階段增多,那么集群利用率就會(huì)增加。

        set hive.exec.parallel=true; //打開(kāi)任務(wù)并行執(zhí)行
        set hive.exec.parallel.thread.number=16; //同一個(gè)sql允許最大并行度,默認(rèn)為8。

        當(dāng)然得是在系統(tǒng)資源比較空閑的時(shí)候才有優(yōu)勢(shì),否則沒(méi)資源,并行也起不來(lái)。

        5. JVM優(yōu)化

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

        Hadoop的默認(rèn)配置通常是使用派生JVM來(lái)執(zhí)行map和Reduce任務(wù)的。這時(shí)JVM的啟動(dòng)過(guò)程可能會(huì)造成相當(dāng)大的開(kāi)銷(xiāo),尤其是執(zhí)行的job包含有成百上千task任務(wù)的情況。JVM重用可以使得JVM實(shí)例在同一個(gè)job中重新使用N次。N的值可以在Hadoop的mapred-site.xml文件中進(jìn)行配置。通常在10-20之間,具體多少需要根據(jù)具體業(yè)務(wù)場(chǎng)景測(cè)試得出。

        <property>
          <name>mapreduce.job.jvm.numtasks</name>
          <value>10</value>
          <description>How many tasks to run per jvm. If set to -1, there is
          no limit. 
          </description>
        </property>

        我們也可以在hive中設(shè)置

        set  mapred.job.reuse.jvm.num.tasks=10; //這個(gè)設(shè)置來(lái)設(shè)置我們的jvm重用

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

        6. 推測(cè)執(zhí)行優(yōu)化

        在分布式集群環(huán)境下,因?yàn)槌绦騜ug(包括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采用了推測(cè)執(zhí)行(Speculative Execution)機(jī)制,它根據(jù)一定的法則推測(cè)出“拖后腿”的任務(wù),并為這樣的任務(wù)啟動(dòng)一個(gè)備份任務(wù),讓該任務(wù)與原始任務(wù)同時(shí)處理同一份數(shù)據(jù),并最終選用最先成功運(yùn)行完成任務(wù)的計(jì)算結(jié)果作為最終結(jié)果。

        設(shè)置開(kāi)啟推測(cè)執(zhí)行參數(shù):Hadoop的mapred-site.xml文件中進(jìn)行配置:

        <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>

        hive本身也提供了配置項(xiàng)來(lái)控制reduce-side的推測(cè)執(zhí)行:

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

        關(guān)于調(diào)優(yōu)這些推測(cè)執(zhí)行變量,還很難給一個(gè)具體的建議。如果用戶(hù)因?yàn)檩斎霐?shù)據(jù)量很大而需要執(zhí)行長(zhǎng)時(shí)間的map或者reduce task的話,那么啟動(dòng)推測(cè)執(zhí)行造成的浪費(fèi)是非常巨大的。


        最后

        代碼優(yōu)化原則:

        • 理透需求原則,這是優(yōu)化的根本;
        • 把握數(shù)據(jù)全鏈路原則,這是優(yōu)化的脈絡(luò);
        • 堅(jiān)持代碼的簡(jiǎn)潔原則,這讓優(yōu)化更加簡(jiǎn)單;
        • 沒(méi)有瓶頸時(shí)談?wù)搩?yōu)化,這是自尋煩惱。

        --end--


        掃描下方二維碼
        添加好友,備注【交流
        可私聊交流,也可進(jìn)資源豐富學(xué)習(xí)群


        更文不易,點(diǎn)個(gè)“在看”支持一下??

        瀏覽 65
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 黑蝴蝶AV | 一起草日韩 | 女人靠逼网站 | 大乳护士喂奶三级hd | 丁香五月综合婷婷 |