前言
??????? Hive作為大數(shù)據(jù)分析領(lǐng)域常用的倉(cāng)庫(kù)工具磷醋,即使是現(xiàn)在流式計(jì)算如火如荼背景下涩禀,Hive依然倍受各大廠商摯愛(ài)褒纲。使用Hive過(guò)程中宛裕,面對(duì)各種各樣的查詢(xún)需求,需要具有針對(duì)性的優(yōu)化下面內(nèi)容就給大家分別介紹下谆奥。
1. 啟用壓縮
???????? 壓縮可以使磁盤(pán)上的數(shù)據(jù)量變小,例如,文本文件格式能夠壓縮40%甚至更高的比例蜕着,這樣可以通過(guò)降低I/O來(lái)提高查詢(xún)速度。除非產(chǎn)生的數(shù)據(jù)用于外部系統(tǒng)红柱,或者存在格式兼容性問(wèn)題承匣,建議總是啟用壓縮。壓縮與解壓縮會(huì)消耗CPU資源锤悄,但是Hive產(chǎn)生的作業(yè)往往是IO密集型的韧骗。因此CPU開(kāi)銷(xiāo)通常不是問(wèn)題。
1.1 查詢(xún)出可用的編解碼器:
set?io.compression.codecs;
結(jié)果如下:
io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec,
??????????org.apache.hadoop.io.compress.DefaultCodec,
??????????org.apache.hadoop.io.compress.BZip2Codec,
??????????org.apache.hadoop.io.compress.SnappyCodec
1.2 啟用中間數(shù)據(jù)壓縮零聚。
???????? 一個(gè)復(fù)雜的Hive查詢(xún)?cè)偬峤缓笈郾ǔ1晦D(zhuǎn)化成一系列中間階段的MapReduce作業(yè),Hive引擎將這些作業(yè)串聯(lián)起來(lái)完成整個(gè)查詢(xún)握牧∪菸埽可以將這些中間數(shù)據(jù)進(jìn)行壓縮。這里所說(shuō)的中間數(shù)據(jù)指的是上一個(gè)MR作業(yè)的輸出沿腰,這個(gè)輸出將會(huì)被下一個(gè)MR作業(yè)作為輸入數(shù)據(jù)使用览徒。
?set?hive.exec.compress.intermediate=true;
?set?hive.intermediate.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;
?set?hive.intermediate.compression.type=BLOCK;
1.3 啟用結(jié)果壓縮
當(dāng)Hive輸出接入到表中時(shí),輸出內(nèi)容同樣可以進(jìn)行壓縮颂龙。
?set?hive.exec.compress.output=true;
?set?mapreduce.output.fileoutputformat.compress=true;
?set?mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;
?set?mapreduce.output.fileoutputformat.compress.type=BLOCK;
2. 優(yōu)化連接查詢(xún)
可以通過(guò)配置Map連接和傾斜連接的相關(guān)屬性提升連接查詢(xún)的性能习蓬。
2.1 自動(dòng)Map連接
???????? 當(dāng)連接一個(gè)大表和一個(gè)小表時(shí),自動(dòng)Map連接是一個(gè)非常有用特性措嵌。如果啟動(dòng)該特性躲叼,小表將保存在每個(gè)節(jié)點(diǎn)的本地緩存中,并在Map節(jié)點(diǎn)與大表進(jìn)行連接企巢。開(kāi)啟自動(dòng)Map連接提供了兩個(gè)好處枫慷。首先,將小標(biāo)裝進(jìn)緩存將節(jié)省每個(gè)數(shù)據(jù)節(jié)點(diǎn)上的讀取時(shí)間浪规。其次或听,它避免了Hive查詢(xún)中的傾斜連接,因?yàn)槊總€(gè)數(shù)據(jù)塊的連接操作已經(jīng)在Map階段完成了笋婿。
set?hive.auto.convert.join=true;
set?hive.auto.convert.join.noconditionaltask=true;
set?hive.auto.convert.join.noconditionaltask.size=100000000;
set?hive.auto.convert.join.use.nonstaged=true;
其中:
- hive.auto.convert.join:是否啟用基于輸入文件的大小誉裆,將普通連接轉(zhuǎn)化為Map連接的優(yōu)化機(jī)制。
- hive.auto.convert.join.noconditionaltask:是否啟用基于輸入文件的大小缸濒,將普通連接轉(zhuǎn)化為Map連接的優(yōu)化機(jī)制足丢。假設(shè)參與連接的表(或分區(qū))有N個(gè)粱腻,如果打開(kāi)這個(gè) 參數(shù),并且有N-1個(gè)表(或分區(qū))的大小總和小于hive.auto.convert.join.noconditionaltask.size參數(shù)指定的值斩跌,那么會(huì)直接將連接轉(zhuǎn)為Map連接绍些。
- hive.auto.convert.join.noconditionaltask.size:如果hive.auto.convert.join.noconditionaltask是關(guān)閉的,則本參數(shù)不起作用滔驶。否則遇革,如果參與連接的N個(gè)表(或分區(qū))中的N-1個(gè) 的總大小小于這個(gè)參數(shù)的值卿闹,則直接將連接轉(zhuǎn)為Map連接揭糕。默認(rèn)值為10MB。
- hive.auto.convert.join.use.nonstaged:對(duì)于條件連接锻霎,如果從一個(gè)小的輸入流可以直接應(yīng)用于join操作而不需要過(guò)濾或者投影著角,那么不需要通過(guò)MapReduce的本地任務(wù)在 分布式緩存中預(yù)存。當(dāng)前該參數(shù)在vectorization或tez執(zhí)行引擎中不工作旋恼。
2.2 傾斜連接
???????? 兩個(gè)大表連接時(shí)吏口,會(huì)先基于連接鍵分別對(duì)兩個(gè)表進(jìn)行排序,然后連接它們冰更。Mapper將特定鍵值的所有行發(fā)送給同一個(gè)Reducer产徊。例如:表A的id列有1,2蜀细,3舟铜,4四個(gè)值,表B的id有1奠衔,2谆刨,3三個(gè)值,查詢(xún)語(yǔ)句如下:
select?A.id?from?A?join?B?on?A.id?=?B.id
???????? 一系列Mapper讀取表中的數(shù)據(jù)并基于鍵發(fā)送給Reducer归斤。如id=1行進(jìn)入Reducer R1,id = 2的行進(jìn)入Reducer R2的行等痊夭。這些Reducer產(chǎn)生A B的交集并輸出。Reducer R4只從A獲取行脏里,不產(chǎn)生查詢(xún)結(jié)果她我。
???????? 現(xiàn)在假設(shè)id=1的數(shù)據(jù)行是高度傾斜的,則R2和R3會(huì)很快完成迫横,而R1需要很長(zhǎng)時(shí)間番舆,將成為整個(gè)查詢(xún)的瓶頸。配置傾斜連接的相關(guān)屬性可以有效優(yōu)化傾斜連接员淫。
set?hive.optimize.skewjoin=true;
set?hive.skewjoin.key=1000000;
set?hive.skewjoin.mapjoin.map.tasks=10000;
set?hive.skewjoin.mapjoin.min.split=33554432;
其中:
- hive.optimize.skewjoin:是否為連接表中的傾斜鍵創(chuàng)建單獨(dú)的執(zhí)行計(jì)劃合蔽。它基于存儲(chǔ)在元數(shù)據(jù)中的傾斜鍵。在編譯時(shí)介返,Hive為傾斜鍵和其他鍵值生成各自的查詢(xún)計(jì)劃拴事。
- hive.skewjoin.key:決定如何確定連接中的傾斜鍵沃斤。在連接操作中,如果同一鍵值所對(duì)應(yīng)的數(shù)據(jù)行數(shù)超過(guò)該參數(shù)值刃宵,則認(rèn)為該鍵是一個(gè)傾斜連接鍵衡瓶。
- hive.skewjoin.mapjoin.map.tasks:指定傾斜連接中,用于Map連接作業(yè)的任務(wù)數(shù)牲证。該參數(shù)應(yīng)該與hive.skewjoin.mapjoin.min.split一起使用哮针,執(zhí)行細(xì)粒度的控制。
- hive.skewjoin.mapjoin.min.split:通過(guò)指定最小split的大小坦袍,確定Map連接作業(yè)的任務(wù)數(shù)十厢。該參數(shù)應(yīng)該與hive.skewjoin.mapjoin.map.tasks一起使用,執(zhí)行細(xì)粒度的控制捂齐。
2.3 桶Map連接
如果連接中使用的表是特定列分桶的蛮放,可以開(kāi)啟桶Map連接提升性能。
set?hive.optimize.bucketmapjoin=true;
set?hive.optimize.bucketmapjoin.sortedmerge=true;
其中:
- hive.optimize.bucketmapjoin:是否嘗試桶Map連接奠宜。
- hive.optimize.bucketmapjoin.sortedmerge:是否嘗試在Map連接中使用歸并排序包颁。
3. 避免使用Order by 全局排序
???????? Hive中使用order by 子句實(shí)現(xiàn)全局排序,order by只用一個(gè)reduce產(chǎn)生結(jié)果压真,對(duì)于大數(shù)據(jù)集娩嚼,這種做法效率很低。如果不需要全局有序滴肿,則可以使用sort by子句岳悟,該子句為每個(gè)reduce生成一個(gè)排好序的文件。如果需要控制一個(gè)特定數(shù)據(jù)行流向哪個(gè)reducer嘴高,可以使用用distribute by 子句竿音。如:
select?id,name,salary,?dept?from?employee?distribute?by?dept?sort?by?id?asc,?name?desc;
???????? 屬于一個(gè)dept的數(shù)據(jù)會(huì)分配到一個(gè)reducer進(jìn)行處理,同一個(gè)dept的所有記錄會(huì)按照id拴驮,name列排序春瞬。最終的結(jié)果集是全局有序的。
4. 啟用Tex或者Spark執(zhí)行引擎套啤。
set?hive.execution.engine=tex;
或者
set?hive.execution.engine=spark;
5. 優(yōu)化Limit操作
???????? 默認(rèn)時(shí)limit操作仍然會(huì)執(zhí)行整個(gè)查詢(xún)宽气,然后返回限定的行數(shù)。在有些情況下這種處理方式很浪費(fèi)潜沦,因此可以通過(guò)設(shè)置下面的屬性避免此行為萄涯。
set?hive.limit.optimize.enable=true;
set?hive.limit.row.max.size=true;
set?hive.limit.optimize.limit.file=10;
set?hive.limit.optimize.fetch.max=50000;
其中:
- hive.limit.optimize.enable:是否啟用limit優(yōu)化。當(dāng)使用limit語(yǔ)句時(shí)唆鸡,對(duì)源數(shù)據(jù)進(jìn)行抽樣涝影。
- hive.limit.row.max.size:在使用limit做數(shù)據(jù)的子集查詢(xún)時(shí)保證的最大行數(shù)據(jù)量。
- hive.limit.optimize.limit.file:在使用limit做數(shù)據(jù)子集查詢(xún)時(shí)争占,采樣的最大文件數(shù)燃逻。
- hive.limit.optimize.fetch.max:使用簡(jiǎn)單limit數(shù)據(jù)抽樣時(shí)序目,允許的最大行數(shù)。
6. 啟用并行執(zhí)行
???????? 每條Hive SQL語(yǔ)句都被轉(zhuǎn)化成一個(gè)或者多個(gè)階段執(zhí)行伯襟,可能是一個(gè)MapReduce階段猿涨,采樣階段,限制階段等姆怪。默認(rèn)時(shí)叛赚,Hive在任意時(shí)刻只能執(zhí)行其中一個(gè)階段。如果組成一個(gè)特定作業(yè)的多個(gè)執(zhí)行階段是彼此獨(dú)立的稽揭,那么它們可以并行執(zhí)行俺附,從而整個(gè)作業(yè)得以更快完成。設(shè)置下面的屬性啟用并執(zhí)行淀衣。
set?hive.exec.parallel=true;
set?hive.exec.parallel.thread.number=8;
其中:
- hive.exec.parallel:是否并行執(zhí)行作業(yè)昙读。
- hive.exec.parallel.thread.number:最多可以并行執(zhí)行的作業(yè)數(shù)召调。
7. 啟用MapReduce嚴(yán)格模式
???????? Hive提供了一個(gè)嚴(yán)格模式膨桥,可以防止用戶(hù)執(zhí)行那些可能產(chǎn)生負(fù)面影響的查詢(xún)。通過(guò)設(shè)置下面的屬性啟用MapReduce嚴(yán)格模式唠叛。
set?hive.mapred.mode=strict
嚴(yán)格模式禁止3種類(lèi)型的查詢(xún)
- 對(duì)于分區(qū)表只嚣,where子句中不包含分區(qū)字段過(guò)濾條件的查詢(xún)不允許執(zhí)行。
- 對(duì)于使用了order by子句的查詢(xún)艺沼,要求必須使用limit子句册舞,否則不允許執(zhí)行。
- 限制笛卡爾積查詢(xún)障般。
8. 使用單一Reducer執(zhí)行多個(gè)Group By
???????? 通過(guò)為group by操作開(kāi)啟單一reduce任務(wù)屬性调鲸,可以將一個(gè)查詢(xún)中的多個(gè)group by操作聯(lián)合發(fā)送給單一MapReduce作業(yè)。
set?hive.multigroupby.singlereducer=true;
9. 控制并行Reduce任務(wù)
???????? Hive通過(guò)將查詢(xún)?nèi)蝿?wù)分成一個(gè)或者多個(gè)MapReduce任務(wù)達(dá)到并行的目的挽荡。確定最佳的mapper個(gè)數(shù)和reducer個(gè)數(shù)取決于多個(gè)變量藐石,例如輸入的數(shù)據(jù)量以及對(duì)這些數(shù)據(jù)執(zhí)行的操作類(lèi)型等。如果有太多的mapper或者reducer任務(wù)定拟,會(huì)導(dǎo)致啟動(dòng)于微、調(diào)度和運(yùn)行作業(yè)過(guò)程產(chǎn)生過(guò)多的開(kāi)銷(xiāo),而設(shè)置的數(shù)量太少青自,那么就可能沒(méi)有重分利用好集群內(nèi)在的并發(fā)性株依。對(duì)于一個(gè)Hive查詢(xún),可以設(shè)置下面的屬性來(lái)控制并行reducer任務(wù)的個(gè)數(shù)延窜。
set?hive.exec.reducers.bytes.per.reducer=256000000;
set?hive.exec.reducers.max=1009;
其中:
- hive.exec.reducers.bytes.per.reducer:每個(gè)reducer的字節(jié)數(shù)恋腕,默認(rèn)值為256MB。Hive是按照輸入的數(shù)據(jù)量大小來(lái)確定reducer個(gè)數(shù)的逆瑞。例如荠藤,如果輸入的數(shù)據(jù)是1GB祈远,將 使用4個(gè)reducer。
- hive.exec.reducers.max:將會(huì)使用的最大reducer個(gè)數(shù)商源。
10. 啟用向量化
???????? 向量化特性在Hive 0.13.1版本中被首次引入车份。通過(guò)查詢(xún)執(zhí)行向量化,使Hive從單行處理數(shù)據(jù)改為批量處理方式牡彻,具體來(lái)說(shuō)是一次1024行而不是原來(lái)的每次只處理一行扫沼,這大大提升了指令流水線(xiàn)和緩存的利用率,從而提高了掃描庄吼、聚合缎除、過(guò)濾和鏈接等操作的性能∽苎埃可以設(shè)置下面的屬性啟用查詢(xún)執(zhí)行向量化器罐。
set?hive.vectorized.execution.enabled=true;
set?hive.vectorized.execution.reduce.enabled=true;
set?hive.vectorized.execution.reduce.groupby.enabled=true;
其中:
- hive.vectorized.execution.enabled:如果該標(biāo)志設(shè)置為true,則開(kāi)啟查詢(xún)執(zhí)行的向量模式渐行,默認(rèn)值為false轰坊。
- hive.vectorized.execution.reduce.enabled:如果該標(biāo)志設(shè)置為true,則開(kāi)啟查詢(xún)執(zhí)行reduce端的向量模式祟印,默認(rèn)值為true肴沫。
- hive.vectorized.execution.reduce.groupby.enabled:如果該標(biāo)志設(shè)置為true,則開(kāi)啟查詢(xún)執(zhí)行reduce端group by操作的向量模式蕴忆,默認(rèn)值為true颤芬。
11. 啟用基于成本的優(yōu)化器
???????? Hive 0.14 版本開(kāi)始提供基于成本優(yōu)化器(CBO)特性。使用過(guò)Oracle數(shù)據(jù)庫(kù)的同學(xué)對(duì)CBO一定不會(huì)陌生套鹅。與Oracle類(lèi)似站蝠,Hive的CBO也可以根據(jù)查詢(xún)成本指定執(zhí)行計(jì)劃,例如確定表鏈接的順序卓鹿、以何種方式執(zhí)行鏈接菱魔、使用的并行度等。設(shè)置下面的屬性啟用基于成本優(yōu)化器减牺。
set?hive.cbo.enable=true;
set?hive.compute.query.using.stats=true;
set?hive.stats.fetch.partition.stats=true;
set?hive.stats.fetch.column.stats=true;
其中:
- hive.cbo.enable:控制是否啟用基于成本的優(yōu)化器豌习,默認(rèn)值是true。Hive的CBO使用Apache Calcite框架實(shí)現(xiàn)拔疚。
- hive.compute.query.using.stats:該屬性的默認(rèn)值為false肥隆。如果設(shè)置為true,Hive在執(zhí)行某些查詢(xún)時(shí)稚失,例如select count(1)栋艳,只利用元數(shù)據(jù)存儲(chǔ)中保存的狀態(tài)信息返回結(jié)果。為了收集基本狀態(tài)信息句各,需要將hive.stats.autogather屬性配置為true吸占。為了收集更多的狀態(tài)信息晴叨,需要運(yùn)行analyzetable查詢(xún)命令。
- hive.stats.fetch.partition.stats:該屬性的默認(rèn)值為true矾屯。操作樹(shù)中所標(biāo)識(shí)的統(tǒng)計(jì)信息兼蕊,需要分區(qū)級(jí)別的基本統(tǒng)計(jì),如每個(gè)分區(qū)的行數(shù)件蚕、數(shù)據(jù)量大小和文件大小等孙技。分區(qū) 統(tǒng)計(jì)信息從元數(shù)據(jù)存儲(chǔ)中獲取。如果存在很多分區(qū)排作,要為每個(gè)分區(qū)收集統(tǒng)計(jì)信息可能會(huì)消耗大量的資源牵啦。這個(gè)標(biāo)志可被用于禁止從元數(shù)據(jù)存儲(chǔ)中獲取分區(qū)統(tǒng)計(jì)。當(dāng) 該標(biāo)志設(shè)置為false時(shí)妄痪,Hive從文件系統(tǒng)獲取文件大小哈雏,并根據(jù)表結(jié)構(gòu)估算行數(shù)。
- hive.stats.fetch.column.stats:該屬性的默認(rèn)值為false衫生。操作樹(shù)中所標(biāo)識(shí)的統(tǒng)計(jì)信息裳瘪,需要列統(tǒng)計(jì)。列統(tǒng)計(jì)信息從元數(shù)據(jù)存儲(chǔ)中獲取障簿。如果存在很多列盹愚,要為每個(gè)列收 集統(tǒng)計(jì)信息可能會(huì)消耗大量的資源。這個(gè)標(biāo)志可被用于禁止從元數(shù)據(jù)存儲(chǔ)中獲取列統(tǒng)計(jì)站故。
可以使用HQL的analyze table語(yǔ)句收集一個(gè)表中所有列相關(guān)的統(tǒng)計(jì)信息,例如下面的語(yǔ)句收集sales_order_face表的統(tǒng)計(jì)信息毅舆。
analyze?table?sales_order_fact?compute?statistics?for?climuns;
analyze?table?sales_order_fact?compute?statistics?for?columns?order_number,customer_sk;
12. 使用合適的存儲(chǔ)格式
???????? Hive支持多種數(shù)據(jù)格式西篓,如textFile、sequenceFile憋活、RCFFile岂津、ORCFile等。在合適的場(chǎng)景下使用合適的存儲(chǔ)格式悦即,有助于提升查詢(xún)性能吮成。
下面是選擇存儲(chǔ)格式建議的場(chǎng)景:
- 如果數(shù)據(jù)有參數(shù)的分隔符,那么可以選擇TEXTFILE格式辜梳。
- 如果數(shù)據(jù)所在文件比塊尺寸小粱甫、可以選擇SEQUCEFILE格式。
- 如果想執(zhí)行數(shù)據(jù)分析作瞄,并高效地存儲(chǔ)數(shù)據(jù)茶宵,可以選擇RCFFILE。
- 如果希望減少數(shù)據(jù)所需要的存儲(chǔ)空間并提升性能宗挥,可以選擇ORCFILE乌庶。
彩蛋
資源獲取 獲取Flink面試題种蝶,Spark面試題,程序員必備軟件瞒大,hive面試題螃征,Hadoop面試題,Docker面試題透敌,簡(jiǎn)歷模板会傲,優(yōu)質(zhì)的文章等資源請(qǐng)去 下方鏈接獲取GitHub自行下載 https://github.com/lhh2002/Framework-Of-BigData?Gitee 自行下載 ?https://gitee.com/li_hey_hey/dashboard/projects