Hive面試

1.描述一下Hive的基本架構(gòu)?

Hive架構(gòu).png

  1. 用戶接口
    • CLI:Shell終端命令行,采用交互式方式與Hive進(jìn)行交互
    • JDBC/ODBC:基于JDBC提供的客戶端,常用的有beeline鏈接hive-server2
    • WEB UI:通過(guò)瀏覽器訪問(wèn)Hive。需要通過(guò)配置(hive-site.xml)開(kāi)啟,不常用。
  2. 跨語(yǔ)言服務(wù)
    • Thrift Server:Thrift是Facebook開(kāi)發(fā)的一款擴(kuò)拓展的、跨語(yǔ)言的服務(wù)框架。Hive可以通過(guò)此框架直接不同變成語(yǔ)言調(diào)用其接口。
  3. Driver
    Driver組件提供了HQL語(yǔ)句的語(yǔ)法分析、變異、優(yōu)化以及生成邏輯執(zhí)行計(jì)劃的全部過(guò)程。邏輯執(zhí)行計(jì)劃最終保存在HDFS中,并隨后由MapReduce調(diào)用。
    • 解釋器(SQL Parser):負(fù)責(zé)將HQL語(yǔ)句轉(zhuǎn)換為抽象語(yǔ)法樹(shù)(AST)。
    • 編譯器(Logical Plan):將抽象語(yǔ)法數(shù)編譯為邏輯執(zhí)行計(jì)劃。
    • 優(yōu)化器(Query Optimizer):對(duì)邏輯執(zhí)行計(jì)劃進(jìn)行優(yōu)化。
    • 執(zhí)行器(Execution):調(diào)用底層運(yùn)行框架執(zhí)行邏輯執(zhí)行計(jì)劃。
  4. MapReduce
    Hive默認(rèn)使用MapReduce框架執(zhí)行HQL任務(wù)。
  5. HDFS
    Hive作為數(shù)據(jù)倉(cāng)庫(kù),本身并不保存數(shù)據(jù),而是將HDFS上的結(jié)構(gòu)化數(shù)據(jù)映射為表。因此Hive執(zhí)行的任務(wù),本質(zhì)上還是調(diào)用HDFS上的結(jié)構(gòu)化數(shù)據(jù)。
  6. Meta Store
    元數(shù)據(jù)(Meta Store)本質(zhì)上就是對(duì)Hive中的庫(kù)、表結(jié)構(gòu)以及HDFS數(shù)據(jù)位置的描述信息。通常保存在MySQL之類的關(guān)系型數(shù)據(jù)庫(kù)中。
    Hive的元數(shù)據(jù)包括:庫(kù)名、表名、表列、表屬性、表分區(qū)、表數(shù)據(jù)位置等。
    Hive編譯器在變異HQL語(yǔ)句時(shí),會(huì)首先調(diào)用MetaStore元數(shù)據(jù)進(jìn)行類型和語(yǔ)法的合法性檢測(cè)。

2.HQL轉(zhuǎn)換為MapReduce的過(guò)程?

  1. 用戶提交HQL語(yǔ)句
  2. 解釋器(SQL Parser)調(diào)用元數(shù)據(jù)對(duì)HQL進(jìn)行類型和語(yǔ)法的合法性檢測(cè),并將HQL轉(zhuǎn)換為抽象語(yǔ)法樹(shù)。
  3. 語(yǔ)義分析器(Semantic Analyzer)遍歷抽象語(yǔ)法樹(shù),抽出任務(wù)的基本組成單元(Query Block)。
  4. 編譯器(Logical Plan)將Query Block編譯為操作樹(shù)(Operator Tree)。
  5. 優(yōu)化器(Query Optimizer)優(yōu)化操作樹(shù),合并不必要的ReduceSinkOperator,減少Shuffle數(shù)據(jù)量。
  6. 遍歷優(yōu)化后的操作樹(shù),生成MapReduce任務(wù)。
  7. 執(zhí)行器提交MapReduce任務(wù)。

3.內(nèi)部表和外部表的區(qū)別

  • 內(nèi)部表(Managed Table),又稱管理表。當(dāng)用戶刪除內(nèi)部表時(shí),HDFS存儲(chǔ)的數(shù)據(jù)會(huì)隨之被刪除。
  • 外部表(Ex't'ranal Table)。用戶建立表時(shí),需要通過(guò)LOCATION關(guān)鍵字指定數(shù)據(jù)保存位置;刪除表時(shí),HDFS數(shù)據(jù)不會(huì)被刪除,只會(huì)刪除元數(shù)據(jù)中的表信息。

4.談一下Hive的特點(diǎn)?Hive與RDBMS的區(qū)別?

  • Hive的特點(diǎn)
    • Hive并不存儲(chǔ)數(shù)據(jù),而是將HDFS上的結(jié)構(gòu)化數(shù)據(jù)映射為表結(jié)構(gòu),其元數(shù)據(jù)可以保存在其他關(guān)系型數(shù)據(jù)庫(kù)中。
    • Hive不支持行級(jí)別的增刪操作,如果需要進(jìn)行更新,只能通過(guò)分區(qū)或者覆蓋的方式進(jìn)行更新。
    • Hive默認(rèn)使用MapReduce作為底層調(diào)度引擎,因此任務(wù)執(zhí)行延遲較高。在小數(shù)據(jù)量情況下,關(guān)系型數(shù)據(jù)庫(kù)執(zhí)行效率遠(yuǎn)超Hive,只有在海量數(shù)據(jù)情況下,Hive的并行化計(jì)算優(yōu)勢(shì)才能體現(xiàn)。
    • Hive可以將HQL轉(zhuǎn)換為MapReduce任務(wù)進(jìn)行數(shù)據(jù)分析,簡(jiǎn)化了MapReduce的學(xué)習(xí)成本。
    • Hive任務(wù)執(zhí)行延遲高,因此不支持實(shí)時(shí)計(jì)算。
    • Hive是基于Hadoop之上構(gòu)建的,因此Hive可以跟隨Hadoop進(jìn)行水平擴(kuò)展。在水平拓展時(shí),只需要部署Hive環(huán)境,并將現(xiàn)有配置文件分發(fā)到該節(jié)點(diǎn)即可。
  • Hive與RDBMS的區(qū)別
    Hive與RDBMS的區(qū)別.png

    圖片來(lái)源于:https://www.cnblogs.com/qingyunzong/p/8707885.html

5.請(qǐng)說(shuō)明Hive中 Order By、Sort By、Distrbute By、Cluster By各代表什么意思?

  • Order By:會(huì)對(duì)輸出做全局排序,因此只會(huì)生成一個(gè)Reduce。如果最終輸出結(jié)果較大,一個(gè)Reduce會(huì)導(dǎo)致任務(wù)的執(zhí)行延遲變高。
  • Sort By:在每個(gè)Reduce內(nèi)部做排序,而非全局排序。因此輸出數(shù)據(jù)不是全局有序。通常與Distrbute By結(jié)合使用。
  • Distrbute By:按照指定的字段,將數(shù)據(jù)劃分到不同的Reduce中去。通常與Sort By結(jié)合使用。
  • Cluster By:CLUSTER BY a等同于DISTRBUTE BY a SORT BY a。

6.談?wù)勀銓?duì)Hive窗口的理解?以及Hive是如何設(shè)置窗口大小的?
Hive的窗口函數(shù)是基于行數(shù)據(jù)的開(kāi)窗,由OVER()關(guān)鍵字指定,通常搭配PARTITION BYORDER BY指定分區(qū)和排序字段,以及ROW BETWEEN指定窗口大小。
Hive窗口大小由ROW BETWEEN關(guān)鍵字指定,由PRECEDING指定當(dāng)前行前,由CURRENT ROW指定當(dāng)前行,由FOLLOWING指定當(dāng)前行后。
如指定首行到當(dāng)前行:

OVER(PARTITON BY a ORDER BY b ROW BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)

指定當(dāng)前行到尾行:

OVER(PARTITON BY a ORDER BY b ROW BETWEEN CURRENT AND UNBOUNDED FOLLOWING)

指定當(dāng)前行前10行到后10行:

OVER(PARTITON BY a ORDER BY b ROW BETWEEN 10 PRECEDING AND 10 FOLLOWING)

7.談?wù)凥ive中的幾個(gè)排名函數(shù)?
Hive的排名函數(shù)共有三個(gè),分別為ROW_NUMBERRANKDENSE_RANK。
ROW_NUMBER:按照排序順序生成排名,不產(chǎn)生重復(fù)名次。
RANK:按照順序生成排名,產(chǎn)生重復(fù)名次,重復(fù)名次會(huì)在排名中留下空位。例如1、2、2、4...
DENSE_RANK:按照順序生成排名,產(chǎn)生重復(fù)名字,重復(fù)名次不會(huì)在排名中留下空位。例如1、2、2、3...

8.描述下Hive中的null是怎么存儲(chǔ)的?
在Hive底層。null作為"\N"進(jìn)行存儲(chǔ)。
在與其他數(shù)據(jù)庫(kù)做交互時(shí),需要提前對(duì)其進(jìn)行處理。如sqoop導(dǎo)出Hive數(shù)據(jù)到MySQL。

9.你常用的內(nèi)置函數(shù)有什么?簡(jiǎn)單描述下它們的作用?
SPLIT:將字符串按照指定分隔符切分為字符串?dāng)?shù)組。如:SELECT SPLIT("a,b,c", ",")
LENGTH:返回字符創(chuàng)長(zhǎng)度。
REVERSE:反轉(zhuǎn)字符串。
SUBSTR:截取字符串。
ARR_CONTAINS:數(shù)組包含。
CASE:類型轉(zhuǎn)換。
REGEXP_REPLACE:正則替換。
PARSE_URL/PARSE_URL_TUPLE:url解析函數(shù)。
GET_JSON_OBJECT:Json解析函數(shù)。
...

10.除了上面的幾個(gè)排名函數(shù),你還用過(guò)什么窗口函數(shù)?

  • LAG:用于統(tǒng)計(jì)當(dāng)前行向前的第N行數(shù)據(jù)。用法LAG(col, n, default),col為列名,n表示第幾行,default為默認(rèn)值。
LAG(age, 5, 18) OVER(PARTITION BY name ORDER BY name)
  • LEAD:與LAG相反,用于統(tǒng)計(jì)當(dāng)前行向后的第N行數(shù)據(jù)。用法LEAD(col, n, default),col為列名,n表示第幾行,default為默認(rèn)值。
LEAD(age, 10, 19) OVER(PARTITION BY name ORDER BY name)
  • FIRST_VALUE:分組排序后,取其第一個(gè)值。用法FIRST_VALUE(col),col為列名。
FIRST_VALUE(age) OVER(PARTITION BY name ORDER BY name)
  • LAST_VALUE:分組排序后,取其截至到當(dāng)前行的最后一個(gè)值。用法LAST_VALUE(col),col為列名。
LAST_VALUE(age) OVER(PARTITION BY name ORDER BY name)

11.列舉下你所知道的列轉(zhuǎn)行函數(shù)?

  • CONCAT(str1, separator1, str2, separator2, str3...):將指定字符串按照指定分隔符進(jìn)行拼接,分隔符只需要指定多次。
  • CONCAT_WS(separator, str1, str2...):將指定字符串按照指定分隔符進(jìn)行拼接,分隔符只需要指定一次。
  • COLLECT_LIST(col):將指定列轉(zhuǎn)換為不去重的數(shù)組。
  • COLLECT_SET(col):將指定列轉(zhuǎn)換為去重的數(shù)組。

12.列舉下你所知道的行專列函數(shù)?

  • EXPLODE(col):將Hive中類型為復(fù)雜類型Array或者HashMap的列轉(zhuǎn)換為多行。
  • LATERAL VIEW():常與UDTF函數(shù)配合使用,將指定列拆分為多行數(shù)據(jù)。
LATERAL VIEW() EXPLODE(SPLIT(a)) tableAlias AS columnAlias

13.COLLECT_LIST()COLLECT_SET() 函數(shù)有什么區(qū)別?
相同點(diǎn):COLLECT_LIST()COLLECT_SET()兩個(gè)函數(shù),都是將一個(gè)列轉(zhuǎn)換為一個(gè)數(shù)組,并返回。
區(qū)別:COLLECT_LIST()轉(zhuǎn)換后的數(shù)組為全部數(shù)據(jù),不進(jìn)行去重;COLLECT_SET()轉(zhuǎn)后的數(shù)組為去重后的數(shù)據(jù)。

14.UDF、UDAF、UDTF的區(qū)別?你有寫過(guò)類似的代碼嗎?

  • UDF(User Defined Function):用戶自定義函數(shù),數(shù)據(jù)為單進(jìn)單出。需要繼承UDF類,并重寫evaluate方法。
  • UDAF(User Defined Aggregation Function):用戶自定義聚合函數(shù),數(shù)據(jù)為多進(jìn)單出。需要繼承UDAF類,并重寫init、iterateterminatePartial、merge、terminate方法。
  • UDTF(User Defined Table-Generating Function):用戶自定義表生成函數(shù),數(shù)據(jù)為單進(jìn)多出。需要繼承GenericUDT類,并重寫initialize, process, close方法。

15.談?wù)勀阍谑褂肏ive過(guò)程中經(jīng)常遇到的幾類問(wèn)題?

  1. 數(shù)據(jù)傾斜導(dǎo)致的OOM。
  2. 數(shù)據(jù)傾斜導(dǎo)致的任務(wù)執(zhí)行時(shí)間過(guò)長(zhǎng)。
  3. ORDER BY導(dǎo)致的任務(wù)執(zhí)行時(shí)間過(guò)長(zhǎng)。

16.Hive數(shù)據(jù)傾斜的原因有哪些?并請(qǐng)舉例一下具體的處理方法?
數(shù)據(jù)傾斜是指:由于數(shù)據(jù)分布不均勻,造成數(shù)據(jù)大量集中在某個(gè)或者某幾個(gè)key上,從而導(dǎo)致的任務(wù)執(zhí)行數(shù)據(jù)過(guò)慢,甚至OOM的情況。
產(chǎn)生數(shù)據(jù)傾斜的原因:

  • Key分布不均勻
  • 業(yè)務(wù)數(shù)據(jù)本身的特性
  • 建表時(shí)考慮不周
  • 數(shù)據(jù)內(nèi)存在大量NULL值
  • 某些HQL本身就存在數(shù)據(jù)傾斜
  1. 使用DISTINCT col導(dǎo)致的數(shù)據(jù)傾斜問(wèn)題。
    因?yàn)樵谑褂?code>DISTINCT進(jìn)行去重操作時(shí),Hive會(huì)默認(rèn)只啟用一個(gè)Reduce進(jìn)行去重,因此會(huì)導(dǎo)致任務(wù)指定速度過(guò)長(zhǎng),甚至產(chǎn)生OOM。
    解決方案:此時(shí)可以使用GROUP BY代替DISTINCT進(jìn)行去重操作,GROUP BY會(huì)根據(jù)key的數(shù)量動(dòng)態(tài)或手動(dòng)指定生成N個(gè)Reduce,可以大幅緩解數(shù)據(jù)傾斜的問(wèn)題。
    GROUP BY去重:
SELECT a FROM b GROUP BY a;

GROUP BY去重統(tǒng)計(jì):

SELECT COUNT(1) cnt FROM (SELECT a FROM b GROUP BY a);
  1. 空值產(chǎn)生的數(shù)據(jù)傾斜問(wèn)題
    在數(shù)據(jù)中,常會(huì)出現(xiàn)某值大量為NULL的情況,此時(shí)如果按照該值進(jìn)行join操作時(shí),就會(huì)出現(xiàn)數(shù)據(jù)傾斜的問(wèn)題。
    解決方案1:過(guò)濾該NULL值,如果業(yè)務(wù)本身不關(guān)心NULL值,則直接丟棄;否則,在join完成后,union該NULL值。
SELECT
      b.userid uderid, a.classname classname, b.username username
FROM
      a
INNER JOIN
      (SELECT userid, username FROM b WHERE userid IS NOT NULL) b
ON
      a.userid = b.userid
UNION ALL
SELECT
      userid, null, username
FROM
      b
WHERE
      userid IS NULL;

解決方案2:為NULL值賦予隨機(jī)值。這種做法可以使得NULL值不被shuffle到一起,從而避免數(shù)據(jù)傾斜的產(chǎn)生。

SELECT
    CASE
        WHEN a.userid LIKE 'hive%' THEN NULL
        ELSE a.userid
    END userid, b.classname classname, c.username username
FROM
    a
LEFT JOIN
    b
ON
    CASE
        WHEN a.userid IS NULL THEN CONNCAT("hive_", RAND())
        ELSE a.userid
    END = b.userid

3.大小表關(guān)聯(lián)產(chǎn)生的數(shù)據(jù)傾斜問(wèn)題。
大小表JOIN產(chǎn)生數(shù)據(jù)傾斜的時(shí)候,可以啟用MAP JOIN將小表直接分發(fā)出去(類似Spark和Flink里的broadcast),這樣小表數(shù)據(jù)將存儲(chǔ)在每個(gè)Executor上,在JOIN的時(shí)候不會(huì)產(chǎn)生reduceTask,因此也就不會(huì)發(fā)生數(shù)據(jù)傾斜的問(wèn)題了。

SELECT /* + MAPJOIN(a) */ a.userid, b.username FROM a INNER JOIN b ON a.userid = b.userid;

在Hive 0.11版本后,MapJoin是默認(rèn)開(kāi)啟的,這個(gè)優(yōu)化策略將有Hive自動(dòng)執(zhí)行。由以下兩個(gè)參數(shù)控制:

SET hive.auto.convert.join=true;  // 開(kāi)啟MapJoin自動(dòng)優(yōu)化
SET hive.mapjoin.smalltable.size=25000000;  // 當(dāng)小表超過(guò)該大小時(shí),MapJoin將自動(dòng)失效。生產(chǎn)環(huán)境中,如果內(nèi)存賦予,可以擴(kuò)大該參數(shù)值。
  1. 大表與大表關(guān)聯(lián)產(chǎn)生的數(shù)據(jù)傾斜問(wèn)題。
    解決方案1: 這種情況下,如果是因?yàn)镹ULL值產(chǎn)生的數(shù)據(jù)傾斜,且業(yè)務(wù)場(chǎng)景對(duì)NULL值并不關(guān)心,則可以提前將NULL過(guò)濾,如此可以避免數(shù)據(jù)傾斜的發(fā)送;如果NULL值過(guò)多,也可能回歸到大小表JOIN的優(yōu)化上去。
    解決方案2:如果業(yè)務(wù)場(chǎng)景對(duì)NULL值有需求,那么此時(shí)可以參照"2. 空值產(chǎn)生的數(shù)據(jù)傾斜問(wèn)題"的解決方案2,為NULL值賦予隨機(jī)值,并在任務(wù)最后將隨機(jī)值還原為NULL值;或者解決方案1,將NULL過(guò)濾,在后續(xù)通過(guò)UNION ALL將數(shù)據(jù)合并。此方案同樣適用于單個(gè)key數(shù)據(jù)量過(guò)大產(chǎn)生的數(shù)據(jù)傾斜問(wèn)題。
    解決方案3:如果業(yè)務(wù)場(chǎng)景是因?yàn)闊狳c(diǎn)數(shù)據(jù)(多個(gè)key值數(shù)據(jù)量特大)問(wèn)題產(chǎn)生的數(shù)據(jù)傾斜,因?yàn)閿?shù)據(jù)量大的key值過(guò)多,此時(shí)不再適用于解決方案2,此時(shí)可以對(duì)所有key都打上一個(gè)隨機(jī)值,此時(shí)將不再根據(jù)原key進(jìn)行shuffle,hash結(jié)果為key_rand,將會(huì)打亂原key進(jìn)行新的hash分組。在最后再將結(jié)果中的rand去除進(jìn)行二次JOIN。
  2. 預(yù)聚合優(yōu)化
    這種優(yōu)化多用在GROUP BY產(chǎn)生數(shù)據(jù)傾斜時(shí),此時(shí)可以通過(guò)參數(shù)開(kāi)啟Hive的預(yù)聚合和負(fù)載均衡優(yōu)化,此時(shí)Hive會(huì)在第一個(gè)MR Job時(shí)將輸出數(shù)據(jù)隨機(jī)分配到Reduce中,在每個(gè)Reduce內(nèi)做預(yù)聚合,此時(shí)相同的key可能分發(fā)到不同的Reduce內(nèi),從而起到負(fù)載均衡的作用;在第二個(gè)MR Job中,Hive按照key進(jìn)行分組,此時(shí)將會(huì)按照key的hash進(jìn)行分組,從而保證結(jié)果的正確性。
SET hive.map.aggr=true;  // 開(kāi)啟預(yù)聚合
SET hive.groupby.skewindata=true;  // 開(kāi)啟數(shù)據(jù)傾斜負(fù)載均衡
  1. 并發(fā)度優(yōu)化
    數(shù)據(jù)傾斜的問(wèn)題,最終還是因?yàn)槟承﹌ey數(shù)據(jù)量過(guò)大而造成的數(shù)據(jù)熱點(diǎn)問(wèn)題。因此在資源充足的情況下,盡可能的在合理的范圍內(nèi)擴(kuò)大Reduce的數(shù)量和任務(wù)資源占有量,可以達(dá)到緩解數(shù)據(jù)傾斜的問(wèn)題。

17.平時(shí)針對(duì)Hive做了什么優(yōu)化?

  1. 建模。合適的建模會(huì)減少很多優(yōu)化的工作量。
  2. 解決數(shù)據(jù)傾斜問(wèn)題。針對(duì)不同的數(shù)據(jù),選擇不同的數(shù)據(jù)傾斜解決方案。
  3. 減少M(fèi)R Job數(shù)量。對(duì)于MR任務(wù)來(lái)說(shuō),Job的啟動(dòng)和銷毀很重,因此減少Job數(shù)量會(huì)極大提高任務(wù)運(yùn)行效率。
  4. 設(shè)置合理的Map和Reduce數(shù)量。Map和Reduce數(shù)量的提高雖然會(huì)緩解數(shù)據(jù)傾斜的問(wèn)題,但是也會(huì)帶來(lái)任務(wù)執(zhí)行效率的降低,因此合適的Map、Reduce數(shù)量將會(huì)加快任務(wù)的執(zhí)行效率。
  5. 充分利用Hive的特性來(lái)對(duì)任務(wù)做優(yōu)化。例如Hive存儲(chǔ)多會(huì)使用Parquet等列存儲(chǔ)方式,因此在符合業(yè)務(wù)場(chǎng)景的情況下,避免使用*的匹配查詢,而選擇單列的查詢。
  6. 盡量減少任務(wù)讀取的數(shù)據(jù)量,合理利用分區(qū)的特性。多使用WHERE對(duì)數(shù)據(jù)進(jìn)行過(guò)濾,可以有效提高任務(wù)執(zhí)行效率。
  7. 使用多表關(guān)聯(lián)時(shí),盡可能利用Map Join的特性。例如小表在左,因?yàn)镠ive會(huì)優(yōu)先嘗試加載左表到內(nèi)存。
  8. 避免使用低效率的函數(shù)。部分Hive函數(shù)會(huì)將Reduce數(shù)量限制為1,在不影響業(yè)務(wù)的情況下,盡可能避免使用之類函數(shù)。例如DISTINCT、ORDER BY
  9. 合并小文件。Hive在讀取文件階段,每個(gè)Block塊都會(huì)生成一個(gè)Map任務(wù),而且小文件對(duì)HDFS影響居多,因此盡可能的使HDFS內(nèi)的文件大小接近128M或者接近128M的倍數(shù)(128M為默認(rèn)的HDFS塊大小,如果有自定義塊大小,需根據(jù)實(shí)際情況調(diào)整)。
  10. HQL并不是語(yǔ)句越復(fù)雜越好,如果有相同需求的情況下,盡可能利用臨時(shí)表或者View來(lái)對(duì)公共中間數(shù)據(jù)做重復(fù)利用。
  11. 盡量不輸出全量數(shù)據(jù),而是使用LIMIT或者ROW_NUMBER等函數(shù)進(jìn)行截取。

18.談?wù)凥ive的分桶表?以及使用場(chǎng)景?
分桶表不同于分區(qū)表。分區(qū)在物理表現(xiàn)形式上為HDFS中的子目錄,而分桶則是利用hash的特性(字段hash值 % 分桶個(gè)數(shù))將數(shù)據(jù)落在不同的文件內(nèi)。
因?yàn)閷?duì)指定字段做了hash,并將其做了歸類,因此在抽樣查詢和Join操作(需要Join的字段為分區(qū)字段)時(shí),會(huì)極大提高讀取效率。
但是分桶表會(huì)加重?cái)?shù)據(jù)加載的負(fù)擔(dān),降低數(shù)據(jù)入庫(kù)的效率,而且在普通的數(shù)據(jù)分析任務(wù)中無(wú)法起到提高效率的能力,因此僅在部分特殊環(huán)境下使用。在實(shí)際環(huán)境中,需酌情考慮。
分桶表常用在需要數(shù)據(jù)抽樣的環(huán)境中(我未在實(shí)際生產(chǎn)環(huán)境中使用過(guò)分桶表,猜測(cè)可能會(huì)對(duì)機(jī)器學(xué)習(xí)或者深度學(xué)習(xí)的環(huán)境中起到作用)。

19.Hive map,reduce數(shù)怎么設(shè)置?怎么優(yōu)化?

  • Map:一般來(lái)說(shuō),MR的Map數(shù)量多保持為由任務(wù)自動(dòng)分配,但是如果HDFS環(huán)境內(nèi)存在大量小文件,針對(duì)小文件做計(jì)算或者單個(gè)文件存在少量字段大量數(shù)據(jù)時(shí),推薦自定義Map任務(wù)數(shù)量。
SET mapred.max.split.size=256000000;  // 每個(gè)Map任務(wù)所能接收數(shù)據(jù)的最大值。
SET mapred.min.split.size=100000000;  // 每個(gè)Map任務(wù)接收數(shù)據(jù)的最小值。
SET mapred.min.split.size.per.node=100000000;  // 一個(gè)節(jié)點(diǎn)上Split的最小值。
SET mapred.min.split.size.per.rack=100000000;  // 一個(gè)交換機(jī)環(huán)境下Split的最小值。
SET set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;  // 對(duì)小文件進(jìn)行聚合。
  • Reduce:Reduce的數(shù)量過(guò)多,會(huì)導(dǎo)致每個(gè)Reduce上處理的數(shù)據(jù)量過(guò)少,任務(wù)效率會(huì)被Reduce任務(wù)的初始化和銷毀過(guò)程嚴(yán)重降低;Reduce的數(shù)量過(guò)少,可能會(huì)出現(xiàn)數(shù)據(jù)傾斜的問(wèn)題。因此Reduce數(shù)量是實(shí)際生產(chǎn)環(huán)境中最常也是最難調(diào)優(yōu)的。
SET hive.exec.reducers.bytes.per.reducer=1000000000;// 每個(gè)Reduce所能承載的數(shù)據(jù)的最大值。默認(rèn)為1G。
SET hive.exec.reducers.max=999;  // 每個(gè)Job中所能產(chǎn)生的Reduce的最大值。默認(rèn)為999。
SET mapred.reduce.tasks=10;  // 設(shè)定Job所產(chǎn)生的Reduce的具體數(shù)量。
  • 合并輸入輸出文件
  1. 合并輸入文件
SET mapred.max.split.size=256000000;  #每個(gè)Map最大輸入大小
SET mapred.min.split.size.per.node=100000000; #一個(gè)節(jié)點(diǎn)上split的至少的大小
SET mapred.min.split.size.per.rack=100000000; #一個(gè)交換機(jī)下split的至少的大小
SET hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;  #執(zhí)行Map前進(jìn)行小文件合并
  1. 合并輸出文件
SET hive.merge.mapfiles = true #在Map-only的任務(wù)結(jié)束時(shí)合并小文件
SET hive.merge.mapredfiles = true #在Map-Reduce的任務(wù)結(jié)束時(shí)合并小文件
SET hive.merge.size.per.task = 256*1000*1000 #合并文件的大小
SET hive.merge.smallfiles.avgsize=16000000 #當(dāng)輸出文件的平均大小小于該值時(shí),啟動(dòng)一個(gè)獨(dú)立的map-reduce任務(wù)進(jìn)行文件merge。
  • 對(duì)中間文件進(jìn)行壓縮
    MR任務(wù)在指定過(guò)程會(huì)產(chǎn)生大量的中間文件,基于MR引擎的Hive也不例外。
    如果在實(shí)際業(yè)務(wù)場(chǎng)景中,處理的數(shù)據(jù)量龐大,但是CPU資源富余,可以采用將中間結(jié)果壓縮的方式,來(lái)減輕shuffle的壓力。
SET hive.exec.compress.intermediate=true;  // 開(kāi)啟中間結(jié)果壓縮
SET hive.intermediate.compression.codec="org.apache.hadoop.io.compress.LzoCodec";  // 設(shè)定壓縮格式為L(zhǎng)ZO。

20.Hive的存儲(chǔ)格式有哪些?你之前選擇了什么存儲(chǔ)格式?為什么?

  • TextFile
    Hive的默認(rèn)存儲(chǔ)方式。文本存儲(chǔ)、行存儲(chǔ)、不支持塊壓縮,磁盤開(kāi)銷大、數(shù)據(jù)解析開(kāi)銷大,不建議生產(chǎn)環(huán)境使用。
  • SequenceFile
    HDFS提供的二進(jìn)制文件格式。行存儲(chǔ),可壓縮、可分割、可切片。
  • RCFile
    早期的行列存儲(chǔ)方式,支持壓縮和快速的查詢性能,寫操作較慢,比行式存儲(chǔ)占用更多的存儲(chǔ)空間。
    RCFile是行、列結(jié)合的存儲(chǔ)方式。首先將數(shù)據(jù)按行分塊,塊數(shù)據(jù)按列存儲(chǔ),避免了一條記錄的多Block讀取,并且列存儲(chǔ)的方式有利于數(shù)據(jù)的壓縮和快速的列讀取。
  • ORCFile
    RCFile的升級(jí)版,同樣是按行分塊,按列存儲(chǔ),但是對(duì)于RCFile讀取效率上有大幅提升。
  • Parquet
    Parquet是純粹的列存儲(chǔ)格式,有很好的壓縮性能,以及快速的列讀取能力。但是寫入速度較慢。
    擁有很好的兼容能力(Impala、Presto等都是基于Parquet的)。
    在生產(chǎn)環(huán)境中,我們選擇了Parquet的列存儲(chǔ)格式,以及Snappy的壓縮格式。選擇Parquet是因?yàn)樗橇写鎯?chǔ),對(duì)于海量數(shù)據(jù)中針對(duì)部分列的讀取有很好的性能,更重要的是,它可以完美兼容Impala和Presto。

21.Hive文件壓縮格式有哪些,壓縮效率如何?
Hive的文件壓縮格式,實(shí)際上就是HDFS的壓縮格式。
HDFS壓縮格式通常有五種:gzip、bzip2、snappy、lzo以及HDFS默認(rèn)的壓縮格式(不常用不做講解)。

壓縮特性.png

壓縮性能.png

數(shù)據(jù)來(lái)自于:https://blog.csdn.net/zhouyan8603/article/details/82954459

22.join操作底層的MapReduce是怎么去執(zhí)行的?
Hive的join操作分為兩種:MapJoin和ReduceJoin。

  • ReduceJoin:在Reduce階段完整Join操作,也是一般的Join。
    在Map階段,輸出以join操作的key的鍵值的數(shù)據(jù),如果join有多個(gè)條件,則以這些key作為鍵值。
    Reduce階段,以這些key完成join操作。
  • MapJoin:大小表Join。
    首先將小表轉(zhuǎn)換為HashTable結(jié)構(gòu),并寫入本地文件中,然后將該文件加載到DistributeCache中去。該任務(wù)為L(zhǎng)ocal任務(wù)。
    然后生成沒(méi)有Reduce的MR任務(wù),讀取每一條數(shù)據(jù)與DistributeCache中的數(shù)據(jù)進(jìn)行關(guān)聯(lián),最終生成結(jié)果。

23.你知道Hive中有幾種去重方式?列出它們的優(yōu)點(diǎn)和缺點(diǎn)?

  1. DISTINCT:用法靈活,可以在一條HQL同時(shí)對(duì)多個(gè)字段進(jìn)行單獨(dú)去重;但是在海量數(shù)據(jù)中會(huì)發(fā)生數(shù)據(jù)傾斜的問(wèn)題。
  2. GROUOP BY:對(duì)海量數(shù)據(jù)有很好的支撐能力;但是對(duì)多個(gè)字段單獨(dú)去重較為復(fù)雜,需要多個(gè)子查詢支撐。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容