一文弄懂Hive基本架構和原理——Hive元數據信息存儲在Hive MetaStore中,Hive 中所有的數據都存儲在 HDFS 中,Hive 中數據模型:Table,External Table,Partition,Bucket;最后將一個SQL變成hadoop MapReduce作業


一文弄懂Hive基本架構和原理
from:https://blog.csdn.net/oTengYue/article/details/91129850

文章目錄

    概述
    Hive架構
    Hive數據模型
    Hive SQL的編譯
    Hive執行計划
    Hive Sql的MapReduce實現原理
        Join的實現原理
        Group By的實現原理
        Distinct的實現原理
    Hive文件壓縮和文件存儲
        Hive建表指定文件格式
        Hive建表指定壓縮
        Hive動態設置壓縮
            Hive中間數據壓縮
            Hive最終數據壓縮
    Hive Map和Reduce數量計算
        Map數量
        Reduce數量
    數據傾斜
        Group by引起的數據傾斜
        Join引起的數據傾斜
            Skew join
            重寫業務邏輯
    Hive性能優化
    常見問題
        請說明hive中 Sort By,Order By,Cluster By,Distrbute By各代表什么意思
        NULL在hive的一般處理
        multi-group新特性的好處?
    參考

概述

Hive是建立在 Hadoop 上的數據倉庫基礎構架。

它提供了一系列的工具,可以用來進行數據提取轉化加載(ETL),這是一種可以存儲、查詢和分析存儲在 Hadoop 中的大規模數據的機制。

Hive 定義了簡單的類 SQL 查詢語言,稱為 HQL,它允許熟悉 SQL 的用戶查詢數據。同時,這個語言也允許熟悉 MapReduce 開發者的開發自定義的 mapper 和 reducer 來處理內建的 mapper 和 reducer 無法完成的復雜的分析工作。

可以將SQL 查詢轉換為MapReduce 的job 在Hadoop集群上執行。

官方文檔:https://cwiki.apache.org/confluence/display/Hive/Home
Hive架構

在這里插入圖片描述
從架構圖上可以很清楚地看出Hive和Hadoop(MapReduce,HDFS)的關系。

    Hive是最上層,即客戶端層或者作業提交層。
    MapReduce/Yarn是中間層,也就是計算層。
    HDFS是底層,也就是存儲層。

facebook的一張架構圖
在這里插入圖片描述
從Facebook的圖上可以看出,Hive主要有QL,MetaStore和Serde三大核心組件構成。QL就是編譯器,也是Hive中最核心的部分。Serde就是Serializer和Deserializer的縮寫,用於序列化和反序列化數據,即讀寫數據。MetaStore對外暴露Thrift API,用於元數據的修改。比如表的增刪改查,分區的增刪改查,表的屬性的修改,分區的屬性的修改等。
Hive數據模型

在這里插入圖片描述

Hive元數據信息存儲在Hive MetaStore中,如文件路徑、文件格式、列、數據類型、分隔符,Hive默認的分格符有三種,分別是A(Ctrl+A)、B和^C,即ASCii碼的1、2和3,分別用於分隔列,分隔列中的數組元素,和元素Key-Value對中的Key和Value。
Hive 中所有的數據都存儲在 HDFS 中,Hive 中包含以下數據模型:Table,External Table,Partition,Bucket。
(1)表table:一個表就是hdfs中的一個目錄
(2)區Partition:表內的一個區就是表的目錄下的一個子目錄
(3)桶Bucket:如果有分區,那么桶就是區下的一個單位,如果表內沒有區,那么桶直接就是表下的單位,桶一般是文件的形式。
Hive SQL的編譯

一條SQL,進入的Hive。經過上述的過程,其實也是一個比較典型的編譯過程變成了一個作業。
在這里插入圖片描述
Hive是如何將SQL轉化為MapReduce任務的,整個編譯過程分為六個階段:

(1)Antlr定義SQL的語法規則,完成SQL詞法,語法解析,將SQL轉化為抽象語法樹AST Tree

(2)遍歷AST Tree,抽象出查詢的基本組成單元QueryBlock

(3)遍歷QueryBlock,翻譯為執行操作樹OperatorTree

(4)邏輯層優化器進行OperatorTree變換,合並不必要的ReduceSinkOperator,減少shuffle數據量

(5)遍歷OperatorTree,翻譯為MapReduce任務

(6)物理層優化器進行MapReduce任務的變換,生成最終的執行計划
Hive執行計划

可以通過查看Explain查看一個一個SQL如何變成MapReduce作業的過程的過程,例如在hive cli中執行:explain sql語句就能看到

官網LanguageManual Explain:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Explain#LanguageManualExplain-TheASTClause
在這里插入圖片描述
下面是執行的一個例子:
Xnip2019-06-06_14-08-13
Hive Sql的MapReduce實現原理

hive把復雜sql分解成多個MapReduce chain執行,各MR的中間結果存在為hdfs的臨時文件,然后鏈式跑完即可獲得最終結果。因此,只需明白其核心即可見微知著,下面介紹join、group by和distinct原理(直接摘抄美團技術團隊的總結,so 感謝):
Join的實現原理

select u.name, o.orderid from order o join user u on o.uid = u.uid;
在map的輸出value中為不同表的數據打上tag標記,在reduce階段根據tag判斷數據來源。MapReduce的過程如下(這里只是說明最基本的Join的實現,還有其他的實現方式)
在這里插入圖片描述
Group By的實現原理

select rank, isonline, count(*) from city group by rank, isonline;
將GroupBy的字段組合為map的輸出key值,利用MapReduce的排序,在reduce階段保存LastKey區分不同的key。MapReduce的過程如下(當然這里只是說明Reduce端的非Hash聚合過程)
在這里插入圖片描述
Distinct的實現原理

select dealid, count(distinct uid) num from order group by dealid;
當只有一個distinct字段時,如果不考慮Map階段的Hash GroupBy,只需要將GroupBy字段和Distinct字段組合為map輸出key,利用mapreduce的排序,同時將GroupBy字段作為reduce的key,在reduce階段保存LastKey即可完成去重
在這里插入圖片描述
Hive文件壓縮和文件存儲

hive對文件的壓縮是對內容的壓縮,也就是說對文件的壓縮不是先生成文件,再對文件壓縮,而是在生成文件時,對其中的內容字段進行壓縮,最終壓縮后,對外仍體現為某種具體的壓縮文件。

常用的壓縮編解碼器如下表:
在這里插入圖片描述

常用的文件格式:
(1) Textfile

    文本格式,Hive的默認格式,數據不壓縮,磁盤開銷大、數據解析開銷大。可結合Gzip、Bzip2使用,但使用Gzip這種方式,hive不會對數據進行切分,從而無法對數據進行並行操作。行式存儲
    對應的hive API為:org.apache.hadoop.mapred.TextInputFormat和org.apache.hive.ql.io.HiveIgnoreKeyTextOutputFormat

(2)SequenceFile

    Hadoop提供的一種二進制文件格式是Hadoop支持的標准文件格式(其他生態系統並不適用),可以直接將對序列化到文件中,所以sequencefile文件不能直接查看,可以通過Hadoop fs -text查看。具有使用方便,可分割,可壓縮,可進行切片。壓縮支持NONE, RECORD, BLOCK(優先)等格式,可進行切片。行式存儲
    對應hive API為:org.apache.hadoop.mapred.SequenceFileInputFormat和org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat

(3)RCFile

    是一種行列存儲相結合的存儲方式,先將數據按行進行分塊再按列式存儲,保證同一條記錄在一個塊上,避免讀取多個塊,有利於數據壓縮和快速進行列存儲。列式存儲
    對應的hive API為:org.apache.hadoop.hive.ql.io.RCFileInputFormat和org.apache.hadoop.hive.ql.io.RCFileOutputFormat

(4)ORCFile

    orcfile是對rcfile的優化,可以提高hive的讀寫、數據處理性能,提供更高的壓縮效率(目前主流選擇之一)。列式存儲

(5)Parquet

    一種列格式, 可提供對其他 hadoop 工具的可移植性, 包括Hive, Drill, Impala, Crunch, and Pig
    對應的hive API為:org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat和org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat

(6)Avro

    Avro是一個數據序列化系統,設計用於支持大批量數據交換的應用。它的主要特點有:支持二進制序列化方式,可以便捷,快速地處理大量數據;動態語言友好,Avro提供的機制使動態語言可以方便地處理Avro數據。
    對應的hive API為:org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat和org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat

幾種文件存儲格式的性能測試結果:
存儲格式     ORC     Sequencefile     Parquet     RCfile     Avro
數據壓縮后大小     1.8G     67.0G     11G     63.8G     66.7G
存儲耗費時間     535.7s     625.8s     537.3s     543.48     544.3
SQL查詢響應速度     19.63s     184.07s     24.22s     88.5s     281.65s

實踐中常用的壓縮+存儲可以選擇(部分)
Textfile+Gzip
SequenceFile+Snappy
ORC+Snappy
Hive建表指定文件格式

[STORED AS file_format]
file_format:
  : SEQUENCEFILE
  | TEXTFILE -- (Default, depending on hive.default.fileformat configuration)
  | RCFILE -- (Note: Available in Hive 0.6.0 and later)
  | ORC -- (Note: Available in Hive 0.11.0 and later)
  | PARQUET -- (Note: Available in Hive 0.13.0 and later)
  | AVRO -- (Note: Available in Hive 0.14.0 and later)
  | JSONFILE -- (Note: Available in Hive 4.0.0 and later)
  | INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

注:
Hive wiki CreateTable:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable
Hive建表指定壓縮

CREATE EXTERNAL TABLE IF NOT EXISTS tb_test(
     id bigint COMMENT 'id',
     name string COMMENT 'name'      
 )
COMMENT 'test table'
PARTITIONED BY (dt string)
STORED AS ORC
tblproperties ('orc.compress'='SNAPPY');

    1
    2
    3
    4
    5
    6
    7
    8

Hive動態設置壓縮
壓縮格式     Hadoop壓縮編碼/解碼器
Deflate     org.apache.hadoop.io.compress.DeflateCodec
gzip     org.apache.hadoop.io.compress.GzipCodec
bzip2     org.apache.hadoop.io.compress.BZip2Codec
LZO     com.hadoop.compression.lzo.LzopCodec
Lz4     org.apache.hadoop.io.compress.Lz4Codec
Snappy     org.apache.hadoop.io.compress.SnappyCodec
Hive中間數據壓縮

hive.exec.compress.intermediate:默認該值為false,設置為true為激活中間數據壓縮功能。就是在MapReduce的shuffle階段對mapper產生的中間結果數據壓縮。在這個階段,優先選擇一個低CPU開銷的算法。

set hive.exec.compress.intermediate=true;
set mapred.map.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;

    1
    2

Hive最終數據壓縮

hive.exec.compress.output:用戶可以對最終生成的Hive表的數據通常也需要壓縮。該參數控制這一功能的激活與禁用,設置為true來聲明將結果文件進行壓縮。

set hive.exec.compress.output=true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;

    1
    2

參考:
Hive支持的文件格式與壓縮算法:https://my.oschina.net/hulubo/blog/915072?tdsourcetag=s_pctim_aiomsg(推薦)
File Formats:https://cwiki.apache.org/confluence/display/Hive/FileFormats
Hive文件存儲格式:https://www.jianshu.com/p/694f044d1c34
Hive壓縮格式:https://www.cnblogs.com/skyl/p/4740301.html
如何在MapReduce中使用SequenceFile數據格式?http://blog.itpub.net/31077337/viewspace-2214505
如何在MapReduce中使用Avro數據格式?http://blog.itpub.net/31077337/viewspace-2214709
Hive Map和Reduce數量計算
Map數量


num_Map_tasks = max[${Mapred.min.split.size},
                min(${dfs.block.size}, ${Mapred.max.split.size})]

    1
    2
    3

    Mapred.min.split.size指的是數據的最小分割單元大小。
    Mapred.max.split.size指的是數據的最大分割單元大小。
    dfs.block.size指的是HDFS設置的數據塊大小。

一般來說dfs.block.size這個值是一個已經指定好的值,而且這個參數Hive是識別不到的,所以實際上只有Mapred.min.split.size和Mapred.max.split.size這兩個參數(本節內容后面就以min和max指代這兩個參數)來決定Map數量。在Hive中min的默認值是1B,max的默認值是256MB。所以如果不做修改的話,就是1個map task處理256MB數據,我們就以調整max為主。通過調整max可以起到調整Map數的作用,減小max可以增加Map數,增大max可以減少Map數 。需要提醒的是,直接調整Mapred.Map.tasks這個參數是沒有效果的。
Reduce數量

這里說的Reduce階段,是指前面流程圖中的Reduce phase(實際的Reduce計算)而非圖中整個Reduce task。Reduce階段優化的主要工作也是選擇合適的Reducetask數量,跟上面的Map優化類似。
與Map優化不同的是,Reduce優化時,可以直接設置Mapred。Reduce。tasks參數從而直接指定Reduce的個數。當然直接指定Reduce個數雖然比較方便,但是不利於自動擴展。Reduce數的設置雖然相較Map更靈活,但是也可以像Map一樣設定一個自動生成規則,這樣運行定時Job的時候就不用擔心原來設置的固定Reduce數會由於數據量的變化而不合適。

Hive估算Reduce數量的時候,使用的是下面的公式:

num_Reduce_tasks = min[${Hive.exec.Reducers.max},
                      (${input.size} / ${ Hive.exec.Reducers.bytes.per.Reducer})]

    1
    2

也就是說,根據輸入的數據量大小來決定Reduce的個數,默認Hive.exec.Reducers.bytes.per.Reducer為1G,而且Reduce個數不能超過一個上限參數值,這個參數的默認取值為999。所以我們可以調整Hive.exec.Reducers.bytes.per.Reducer來設置Reduce個數。
數據傾斜

定義: 由於數據分布不均勻,造成數據熱點。

現象: 一個或幾個key的記錄數與平均記錄數差異過大,最長時長遠大於平均時長。任務進度長時間維持在99%(或100%),查看任務監控頁面,發現只有少量(1個或幾個)reduce子任務未完成。

數據傾斜優化:一般分為join引起和group by引起分別解決。
操作     原因     現象
Group by     分組key集中     處理某key值的reduce非常耗時
Join     關聯key集中(例如關聯字段空值過多)     處理某key值的reduce非常耗時
Group by引起的數據傾斜

分兩方面優化:
第一個:
set hive.map.aggr=true;
set hive.groupby.mapaggr.checkinterval=100000;
set hive.map.aggr.hash.min.reduction=0.5;
hive.map.aggr=true(默認)參數控制在group by的時候是否map局部聚合,但也不是都會局部聚合,如果聚合前后差別不是很大,聚合也就沒什么意義了。
后兩個設置是判斷是否需要做map局部聚合,即:預先取100000條數據聚合,如果聚合后的條數/100000>0.5,則不再聚合。

第二個:
set Hive.groupby.skewindata=true;
控制啟動兩個MR Job完成,第一個Job先不按GroupBy字段分發,而是隨機分發做一次聚合,然后啟動第二個Job,拿前面聚合過的數據按GroupBy字段分發計算出最終結果。但是否生效還存在限制,詳情見 Hive-hive.groupby.skewindata配置相關問題調研
Join引起的數據傾斜

優化主要分兩個方向:skew join和重寫業務邏輯
Skew join

set hive.optimize.skewjoin=true;
set hive.skewjoin.key=100000;
記錄超過hive.skewjoin.key(默認100000)閾值的key值先寫入hdfs,然后再進行一個map join的job任務,最終和其他key值的結果合並為最終結果。其過程如下圖:
在這里插入圖片描述
重寫業務邏輯

這個需要結合具體的場景重寫,例如:在日志表與用戶表關聯時候(通過user_id關聯),直接關聯可能導致user_id為null的發生數據傾斜,此時可以把日志表中user_id為null的單獨處理,如下:

SELECT a.xx, b.yy FROM log a JOIN users b
            ON a.user_id IS NOT NULL
                AND a.user_id = b.user_id
UNION ALL
SELECT a.xx, NULL AS yy FROM log a WHERE a.user_id IS NULL;

    1
    2
    3
    4
    5

參考:
HiveQL中如何排查數據傾斜問題:https://blog.csdn.net/u012151684/article/details/77074356
Hive性能優化

見另一篇博文 Hive常用優化參數
常見問題
請說明hive中 Sort By,Order By,Cluster By,Distrbute By各代表什么意思

    order by:會對輸入做全局排序,因此只有一個reducer(多個reducer無法保證全局有序)。只有一個reducer,會導致當輸入規模較大時,需要較長的計算時間。

    sort by:對分區內的數據進行排序,不是全局排序,其在數據進入reducer前完成排序。

    distribute by:對map輸出進行分區,按照指定的字段對數據進行划分輸出到不同的reduce中。常和sort by一起使用,例如:select mid, money, name from store distribute by mid sort by mid asc, money asc

    cluster by:當 distribute by 和 sorts by 字段相同時,可使用 cluster by 方式替代,cluster by 具有 distribute by 和 sort by 的組合功能。但是排序只能是升序排序,不能指定排序規則為ASC或者DESC

NULL在hive的一般處理

NULL默認的存儲都是\N,可以在建表時通過serialization.null.format的設置。
NULL 值的過濾,一般是is null 和 is not null。
multi-group新特性的好處?

multi group by 可以將查詢中的多個group by操作組裝到一個MapReduce任務中,起到優化作用。例如:


from area
    insert overwrite table temp1
        select Provice,city,county,count(rainfall) from area where data="2018-09-02" group by provice,city,count
    insert overwrite table temp2
        select Provice,count(rainfall) from area where data="2018-09-02" group by provice

參考

官方文檔:https://cwiki.apache.org/confluence/display/Hive/Home
HiveSQL的編譯過程(美團):https://tech.meituan.com/2014/02/12/hive-sql-to-mapreduce.html
HiveSQL編譯過程: https://www.slideshare.net/recruitcojp/internal-hive
Hive的核心原理以及查詢優化:http://www.pianshen.com/article/4247149029
深入淺出數據倉庫中SQL性能優化之Hive篇:http://www.codeceo.com/article/sql-hive.html
————————————————
版權聲明:本文為CSDN博主「HaiwiSong」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/oTengYue/article/details/91129850


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM