先說(shuō)一些廢話
總結(jié)一下Hive面試寶典,方便讀者快速過(guò)一遍Hive面試所需要的知識(shí)點(diǎn)
Hive的介紹
Hive和Hadoop的關(guān)系
- Hive利用hdfs存儲(chǔ)數(shù)據(jù),利用MapReduce查詢數(shù)據(jù)
- Hive的數(shù)據(jù)存儲(chǔ)在hdfs上,簡(jiǎn)單的說(shuō)Hive就是hdfs的簡(jiǎn)單一種映射,比如:Hive的一張表映射hdfs上的一個(gè)文件,Hive的一個(gè)數(shù)據(jù)庫(kù)就映射為hdfs上的文件夾
- Hive是一個(gè)計(jì)算框架,他是MapReduce的一種封裝,實(shí)際上他的底層還是MR,Hive就是用人們熟悉的sql對(duì)數(shù)據(jù)進(jìn)行分析的
- Hive執(zhí)行程序是運(yùn)行在Yarn上的
Hive的特點(diǎn)
- Hive可以自由的擴(kuò)展集群的規(guī)模,一般情況下不需要重啟服務(wù)(世界上最大的Hadoop集群在Yahoo!,2009年的規(guī)模在4000臺(tái)節(jié)點(diǎn)左右)
- Hive支持用戶自定義函數(shù),用戶可以根據(jù)自己的需求來(lái)實(shí)現(xiàn)自己的函數(shù)(可能會(huì)引申自定義函數(shù))
- 良好的容錯(cuò)性,節(jié)點(diǎn)出現(xiàn)問(wèn)題SQL仍可完成執(zhí)行(可能會(huì)拓展數(shù)據(jù)傾斜相關(guān)問(wèn)題,或者直接問(wèn)你你工作中有沒(méi)有遇到這樣的問(wèn)題)
Hive的缺點(diǎn)
- Hive的HQL表達(dá)能力有限。迭代式算法無(wú)法表達(dá);數(shù)據(jù)挖掘方面不擅長(zhǎng)
- Hive的效率比較低。Hive自動(dòng)生成的MapReduce作業(yè),通常情況下不夠智能化;Hive調(diào)優(yōu)比較困難,粒度較粗
- Hive執(zhí)行延遲
- Hive 在查詢數(shù)據(jù)的時(shí)候,由于沒(méi)有索引,需要掃描整個(gè)表,因此延遲較高
- 另外一個(gè)導(dǎo)致 Hive 執(zhí)行延遲高的因素是 MapReduce框架,由于MapReduce 本身具有較高的延遲,因此在利用MapReduce 執(zhí)行Hive查詢時(shí),也會(huì)有較高的延遲
- 相對(duì)的,數(shù)據(jù)庫(kù)的執(zhí)行延遲較低。當(dāng)然,這個(gè)低是有條件的,即數(shù)據(jù)規(guī)模較小,當(dāng)數(shù)據(jù)規(guī)模大到超過(guò)數(shù)據(jù)庫(kù)的處理能力的時(shí)候,Hive的并行計(jì)算顯然能體現(xiàn)出優(yōu)勢(shì)
Hive常見的應(yīng)用場(chǎng)景
- 日志分析:大部分互聯(lián)網(wǎng)公司使用Hive進(jìn)行日志分析,包括百度、淘寶等
- 統(tǒng)計(jì)網(wǎng)站一個(gè)時(shí)間段內(nèi)的pv、uv
- 多維度數(shù)據(jù)分析
- 海量結(jié)構(gòu)化數(shù)據(jù)離線分析
Hive和mysql的區(qū)別
- Hive采用了類SQL的查詢語(yǔ)言HQL(hive query language),除了HQL之外,其余無(wú)任何相似的地方,Hive是為了數(shù)據(jù)倉(cāng)庫(kù)設(shè)計(jì)的
- 存儲(chǔ)位置:Hive在Hadoop上;mysql將數(shù)據(jù)存儲(chǔ)在設(shè)備或本地系統(tǒng)中
- 數(shù)據(jù)更新:Hive不支持?jǐn)?shù)據(jù)的改寫和添加,是在加載的時(shí)候就已經(jīng)確定好了;數(shù)據(jù)庫(kù)可以CRUD
- 索引:Hive無(wú)索引,每次掃描所有數(shù)據(jù),底層是MR,并行計(jì)算,適用于大數(shù)據(jù)量;mysql有索引,適合在線查詢數(shù)據(jù)
- 執(zhí)行:Hive底層是MarReduce;mysql底層是執(zhí)行引擎
- 可擴(kuò)展性:Hive:大數(shù)據(jù)量,慢慢擴(kuò)去吧;mysql:相對(duì)就很少了
Hive的架構(gòu)
# Hive架構(gòu)簡(jiǎn)易示意
Meta Store ->
Client (CLI/JDBC/WebGUI +
Driver/驅(qū)動(dòng) +
SQL Parser/解析器 +
Physical Plan/編譯器 +
QueryOptimizer/優(yōu)化器 +
Execution/執(zhí)行器) ->
MapReduce ->
HDFS
- 用戶接口:Hive 對(duì)外提供了三種服務(wù)模式,即 Hive 命令行模式(CLI),Hive 的 Web 模式(WUI),Hive 的遠(yuǎn)程服務(wù)(Client)
- 其中最常用的是 CLI shell 命令行,CLI 啟動(dòng)的時(shí)候,會(huì)同時(shí)啟動(dòng)一個(gè)Hive副本
- WUI 是通過(guò)瀏覽器訪問(wèn) Hive,默認(rèn)端口是9999
- Client 是Hive的客戶端,,在啟動(dòng) Client模式 的時(shí)候,需要指出 Hive Server 所在節(jié)點(diǎn),并且在該節(jié)點(diǎn)啟動(dòng) Hive Server
- JDBC/ODBC用 JAVA 實(shí)現(xiàn),與傳統(tǒng)數(shù)據(jù)庫(kù) JDBC 類似
- 元數(shù)據(jù)存儲(chǔ):通常是存儲(chǔ)在關(guān)系數(shù)據(jù)庫(kù)如 mysql , derby中
- Hive中的元數(shù)據(jù)包括表的名字,表的列和分區(qū)及其屬性,表的屬性(是否為外部表等),表的數(shù)據(jù)所在目錄等
- 解釋器、編譯器、優(yōu)化器、執(zhí)行器
- 解釋器、編譯器、優(yōu)化器完成 HQL 查詢語(yǔ)句從詞法分析、語(yǔ)法分析、編譯、優(yōu)化以及查詢計(jì)劃的生成
- 生成的查詢計(jì)劃存儲(chǔ)在 HDFS 中,并在隨后有 MapReduce 調(diào)用執(zhí)行(注意?。?!包含*的查詢,比如select * from tbl不會(huì)生成MapRedcue任務(wù))
- ===============================================================
- 解析器(parser):將查詢字符串轉(zhuǎn)化為解析樹表達(dá)式
- ===============================================================
- 編譯器(physical plan):分為
語(yǔ)義分析器(semantic analyzer)和邏輯策略生成器(logical plan generator) - 語(yǔ)義分析器(semantic analyzer):將解析樹表達(dá)式轉(zhuǎn)換為基于塊(block-based)的內(nèi)部查詢表達(dá)式
- 邏輯策略生成器(logical plan generator):將內(nèi)部查詢表達(dá)式轉(zhuǎn)換為邏輯策略,這些策略由邏輯操作樹組成
- ===============================================================
- 優(yōu)化器(optimizer):通過(guò)邏輯策略構(gòu)造多途徑并以不同方式重寫
Hive的數(shù)據(jù)
Hive的數(shù)據(jù)模型
- Hive中所有的數(shù)據(jù)都存儲(chǔ)在hdfs中,沒(méi)有專門的數(shù)據(jù)存儲(chǔ)格式(可支持TextFile,SequenceFile,ParquetFile,RCFILE等)
- 只需要在創(chuàng)建表的時(shí)候告訴Hive數(shù)據(jù)中的列分隔符和行分隔符,Hive就可以解析數(shù)據(jù)
- Hive中包含以下數(shù)據(jù)模型:DB、Table、External Table、Partition、Bucket
- DB:在hdfs中表現(xiàn)為
${hive.metastore.warehouse.dir}目錄下一個(gè)文件夾 - Table:在hdfs中表現(xiàn)所屬db目錄下一個(gè)文件夾,普通表刪除表后,hdfs上的文件都刪了
- External Table:外部表, 與table類似,不過(guò)其數(shù)據(jù)存放位置可以在任意指定路徑,外部表刪除后,hdfs上的文件沒(méi)有刪除,只是把文件刪除了
- Partition:在hdfs中表現(xiàn)為table目錄下的子目錄
- Bucket:桶在hdfs中表現(xiàn)為同一個(gè)表目錄下根據(jù)hash散列之后的多個(gè)文件,會(huì)根據(jù)不同的文件把數(shù)據(jù)放到不同的文件中
- DB:在hdfs中表現(xiàn)為
Hive的底層如何存儲(chǔ)Null值
- Null在Hive底層默認(rèn)是用'\N'來(lái)存儲(chǔ)的
- 能夠經(jīng)過(guò)
alter table test SET SERDEPROPERTIES('serialization.null.format' = 'a');來(lái)修改
Hive中元數(shù)據(jù)metadata和元數(shù)據(jù)商店metastore的作用
- metadata即元數(shù)據(jù),元數(shù)據(jù)包含用Hive創(chuàng)建的database、tabel等的元信息,元數(shù)據(jù)存儲(chǔ)在
關(guān)系型數(shù)據(jù)庫(kù)(RDBMS)中,如derby、mysql等 - metastore的作用是:客戶端連接metastore服務(wù),metastore再去連接mysql數(shù)據(jù)庫(kù)來(lái)存取元數(shù)據(jù),
有了metastore服務(wù),就可以有多個(gè)客戶端同時(shí)連接,而且這些客戶端不需要知道m(xù)ysql數(shù)據(jù)庫(kù)的用戶名和密碼,只需要連接metastore服務(wù)即可
Hive有哪些保存元數(shù)據(jù)metadata的方式
- 內(nèi)嵌模式:將元數(shù)據(jù)保存在本地內(nèi)嵌的derby數(shù)據(jù)庫(kù)中,內(nèi)嵌的derby數(shù)據(jù)庫(kù)每次只能訪問(wèn)一個(gè)數(shù)據(jù)文件,也就意味著它不支持多會(huì)話連接,適用于用來(lái)實(shí)驗(yàn),不適用于生產(chǎn)環(huán)境
- 本地模式:將元數(shù)據(jù)保存在本地獨(dú)立的數(shù)據(jù)庫(kù)中(一般是mysql),這可以支持多會(huì)話連接
- 遠(yuǎn)程模式:把元數(shù)據(jù)保存在遠(yuǎn)程獨(dú)立的mysql數(shù)據(jù)庫(kù)中,避免每個(gè)客戶端都去安裝mysql數(shù)據(jù)庫(kù)
- 需要注意的是: 內(nèi)存數(shù)據(jù)庫(kù)derby,安裝小,但是數(shù)據(jù)存在內(nèi)存,不穩(wěn)定。mysql數(shù)據(jù)庫(kù),數(shù)據(jù)存儲(chǔ)模式可以自己設(shè)置,持久化好,查看方便
Hive元數(shù)據(jù)存儲(chǔ)方式中,本地模式和遠(yuǎn)程模式的區(qū)別
- 本地元存儲(chǔ)和遠(yuǎn)程元存儲(chǔ)都采用外部數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)元數(shù)據(jù)
- 本地元存儲(chǔ)不需要單獨(dú)起metastore服務(wù),用的是跟Hive在同一個(gè)進(jìn)程里的metastore服務(wù)
- 遠(yuǎn)程元存儲(chǔ)需要單獨(dú)起metastore服務(wù),然后每個(gè)客戶端都在配置文件里配置連接到該metastore服務(wù),遠(yuǎn)程元存儲(chǔ)的metastore服務(wù)和Hive運(yùn)行在不同的進(jìn)程
Hive的數(shù)據(jù)類型
- 基本數(shù)據(jù)類型,因?yàn)镠ive的底層是用java開發(fā),所以基本數(shù)據(jù)類型和java保持一致
- 整型 tinyint(字節(jié)整型) / smallint(短整型) / int(整型) / bigint(長(zhǎng)整型),分別占用1/2/4/8個(gè)字節(jié),等價(jià)于java的 byte/short/int/long
- 浮點(diǎn)型 float(浮點(diǎn)型) / double(雙精度浮點(diǎn)型),分別占用4/8個(gè)字節(jié),等價(jià)于java的 float/double
- 字符型 string,等價(jià)于數(shù)據(jù)庫(kù)的 varchar,可變字符串,理論上可以存儲(chǔ)2GB的字節(jié)
- 布爾型 boolean,等價(jià)于java的 boolean
- 復(fù)雜數(shù)據(jù)類型
- array/map,等價(jià)于java的array/map
- struct,等價(jià)于c語(yǔ)言中的struct
- 類型轉(zhuǎn)換
- Hive 的原子數(shù)據(jù)類型是可以進(jìn)行隱式轉(zhuǎn)換的,類似于 Java 的類型轉(zhuǎn)換
- 例如某表達(dá)式使用 int 類型,tinyint 會(huì)自動(dòng)轉(zhuǎn)換為 int 類型
- 但是 Hive 不會(huì)進(jìn)行反向轉(zhuǎn)化,例如,某表達(dá)式使用 tinyint 類型,int 不會(huì)自動(dòng)轉(zhuǎn)換為 tinyint 類型,它會(huì)返回錯(cuò)誤,除非使用 CAST 操作
- ===============================================================
- 可以使用 CAST 操作顯示進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換
- 例如 CAST('1' AS INT) 將把字符串'1' 轉(zhuǎn)換成整數(shù) 1
- 如果強(qiáng)制類型轉(zhuǎn)換失敗,如執(zhí)行 CAST('X' AS INT),表達(dá)式返回空值 NULL
Hive的隱式類型轉(zhuǎn)換規(guī)則
- 任何整數(shù)類型都可以隱式地轉(zhuǎn)換為一個(gè)范圍更廣的類型,如 tinyint 可以轉(zhuǎn)換成 int,int 可以轉(zhuǎn)換成 bigint
- 所有整數(shù)類型、float 和 string 類型都可以隱式地轉(zhuǎn)換成 double
- tinyint、smallint、int 都可以轉(zhuǎn)換為 float
- boolean 類型不可以轉(zhuǎn)換為任何其它的類型
Hive數(shù)據(jù)存儲(chǔ)所使用的文件格式
- 默認(rèn)是TextFile文件格式
- 文本格式,Hive的默認(rèn)格式,數(shù)據(jù)不壓縮,磁盤開銷大、數(shù)據(jù)解析開銷大
- 對(duì)應(yīng)的Hive API為:
org.apache.hadoop.mapred.TextInputFormat和org.apache.hive.ql.io.HiveIgnoreKeyTextOutputFormat; - 可結(jié)合Gzip、Bzip2使用(系統(tǒng)自動(dòng)檢查,執(zhí)行查詢時(shí)自動(dòng)解壓),但是使用這種方式,hive不會(huì)對(duì)數(shù)據(jù)進(jìn)行切分,從而無(wú)法對(duì)數(shù)據(jù)進(jìn)行并行操作
- RCFile文件格式
- RCFile是一種行列存儲(chǔ)相結(jié)合的存儲(chǔ)方式,先將數(shù)據(jù)按行進(jìn)行分塊再按列式存儲(chǔ),保證同一條記錄在一個(gè)塊上,避免讀取多個(gè)塊,有利于數(shù)據(jù)壓縮和快速進(jìn)行列存儲(chǔ)
- 對(duì)應(yīng)Hive API為:
org.apache.hadoop.hive.ql.io.RCFileInputFormat和org.apache.hadoop.hive.ql.io.RCFileOutputFormat;
- ORCFile文件格式
- 數(shù)據(jù)按行分塊,每塊按照列存儲(chǔ),不是真正意義上的列存儲(chǔ),可以理解為分段列存儲(chǔ)
- 用于降低Hadoop數(shù)據(jù)存儲(chǔ)空間和加速Hive查詢速度
- ORCfile特點(diǎn)是壓縮比比較高,壓縮快,快速列存取,是RCfile的改良版本,相比RCfile能夠更好的壓縮,更快的查詢
- 需要注意的是ORC在讀寫時(shí)候需要消耗額外的CPU資源來(lái)壓縮和解壓縮,當(dāng)然這部分的CPU消耗是非常少的
- 優(yōu)點(diǎn):
每個(gè)task只輸出單個(gè)文件,減少namenode負(fù)載; 支持各種復(fù)雜的數(shù)據(jù)類型,比如:datetime,decima以及復(fù)雜類型struct、list、map; 文件中存儲(chǔ)了一些輕量級(jí)的索引數(shù)據(jù); 基于數(shù)據(jù)類型的塊模式壓縮:integer類型的列用行程長(zhǎng)度編碼,string類型的列使用字典編碼; 用多個(gè)相互獨(dú)立的recordReaders并行讀相同的文件 無(wú)需掃描markers即可分割文件 綁定讀寫所需內(nèi)存 metadata存儲(chǔ)用protocol buffers,支持添加和刪除列 - SequenceFile文件格式
- Hadoop提供的二進(jìn)制文件,Hadoop支持的標(biāo)準(zhǔn)文件
- 數(shù)據(jù)直接序列化到文件中,SequenceFile文件不能直接查看,可以通過(guò)Hadoop fs -text查看
- SequenceFile具有使用方便、可分割、可壓縮、可進(jìn)行切片,壓縮支持NONE、RECORD、BLOCK(優(yōu)先)
- 對(duì)應(yīng)Hive API:
org.apache.hadoop.mapred.SequenceFileInputFormat和org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat;
- Parquet文件格式
- 二進(jìn)制存儲(chǔ),面向分析性的存儲(chǔ)格式
- 能夠很好的壓縮,同時(shí)減少大量的表掃描和反序列化的時(shí)間,有很好的查詢性能,支持有限的模式演進(jìn),但是寫速度通常比較慢
- Parquet文件是以二進(jìn)制方式存儲(chǔ)的,所以是不可以直接讀取的,文件中包括該文件的數(shù)據(jù)和元數(shù)據(jù),因此Parquet格式文件是自解析的
- 總結(jié)
- TextFile 存儲(chǔ)空間消耗比較大,并且壓縮的text無(wú)法分割和合并查詢的效率最低,可以直接存儲(chǔ),加載數(shù)據(jù)的速度最高
- SequenceFile 存儲(chǔ)空間消耗最大,壓縮的文件可以分割和合并,查詢效率高
- ORCFile / RCFile 存儲(chǔ)空間最小,查詢的效率最高,加載的速度最低
- Parquet 格式是列式存儲(chǔ),有很好的壓縮性能和表掃描功能
- SequenceFile / ORCFile / RCFile 格式的表不能直接從本地文件導(dǎo)入數(shù)據(jù),數(shù)據(jù)要先導(dǎo)入到TextFile格式的表中,
然后再?gòu)腡extFile表中導(dǎo)入到SequenceFile/ORCFile/RCFile表中
Hive中使用的壓縮算法
- 我們?cè)紨?shù)據(jù)使用的是LZO的壓縮格式,因?yàn)樵紨?shù)據(jù)比較大,所以選擇了支持切割的LZO壓縮
- 清洗過(guò)的數(shù)據(jù)存到DWD層,我們?cè)贒WS中需要對(duì)清洗后的數(shù)據(jù)進(jìn)行分析,所以我們DWD層使用的存儲(chǔ)格式是Parquet,壓縮格式是Snappy
- 之前我們壓縮還遇到過(guò)一個(gè)問(wèn)題,當(dāng)時(shí)之前的項(xiàng)目中使用的是Snappy+ORC存儲(chǔ),后來(lái)我發(fā)現(xiàn)使用Snappy+ORC 存儲(chǔ)比ORC單獨(dú)存儲(chǔ)還多占用了近一半的空間
- 后來(lái)我又對(duì)各個(gè)壓縮格式及存儲(chǔ)格式的結(jié)合做了一個(gè)測(cè)試,最終單獨(dú)使用ORC存儲(chǔ)節(jié)省了大量的空間
- Snappy壓縮格式
- 其中壓縮比bzip2 > zlib > gzip > deflate > snappy > lzo > lz4,在不同的測(cè)試場(chǎng)景中,會(huì)有差異,這僅僅是一個(gè)大概的排名情況
- bzip2、zlib、gzip、deflate可以保證最小的壓縮,但在運(yùn)算中過(guò)于消耗時(shí)間
- 從壓縮性能上來(lái)看:lz4 > lzo > snappy > deflate > gzip > bzip2,其中l(wèi)z4、lzo、snappy壓縮和解壓縮速度快,壓縮比低
- 所以一般在生產(chǎn)環(huán)境中,經(jīng)常會(huì)采用lz4、lzo、snappy壓縮,以保證運(yùn)算效率
什么是數(shù)據(jù)可分割
在考慮如何壓縮那些將由MapReduce處理的數(shù)據(jù)時(shí),考慮壓縮格式是否支持分割是很重要的。
考慮存儲(chǔ)在HDFS中的未壓縮的文件,其大小為1GB,HDFS的塊大小為64MB,所以該文件將被存儲(chǔ)為16塊。
將此文件用作輸入的MapReduce作業(yè)會(huì)創(chuàng)建1個(gè)輸人分片(split,也稱為“分塊”。對(duì)于block,我們統(tǒng)一稱為“塊”。)
每個(gè)分片都被作為一個(gè)獨(dú)立map任務(wù)的輸入單獨(dú)進(jìn)行處理現(xiàn)在假設(shè),該文件是一個(gè)gzip格式的壓縮文件,壓縮后的大小為1GB。和前面一樣,HDFS將此文件存儲(chǔ)為16塊。
然而,針對(duì)每一塊創(chuàng)建一個(gè)分塊是沒(méi)有用的,因?yàn)椴豢赡軓膅zip數(shù)據(jù)流中的任意點(diǎn)開始讀取,map任務(wù)也不可能獨(dú)立于其他分塊只讀取一個(gè)分塊中的數(shù)據(jù)。
gzip格式使用DEFLATE來(lái)存儲(chǔ)壓縮過(guò)的數(shù)據(jù),DEFLATE將數(shù)據(jù)作為一系列壓縮過(guò)的塊進(jìn)行存儲(chǔ)。
問(wèn)題是,每塊的開始沒(méi)有指定用戶在數(shù)據(jù)流中任意點(diǎn)定位到下一個(gè)塊的起始位置,而是其自身與數(shù)據(jù)流同步。
因此,gzip不支持分割(塊)機(jī)制。在這種情況下,MapReduce不分割gzip格式的文件,因?yàn)樗垒斎胧莋zip壓縮格式的(通過(guò)文件擴(kuò)展名得知),而gzip壓縮機(jī)制不支持分割機(jī)制。
因此一個(gè)map任務(wù)將處理16個(gè)HDFS塊,且大都不是map的本地?cái)?shù)據(jù)。
與此同時(shí),因?yàn)閙ap任務(wù)少,所以作業(yè)分割的粒度不夠細(xì),從而導(dǎo)致運(yùn)行時(shí)間變長(zhǎng)。
關(guān)于壓縮模式說(shuō)明
- 壓縮模式評(píng)價(jià):
可使用以下三種標(biāo)準(zhǔn)對(duì)壓縮方式進(jìn)行評(píng)價(jià): 壓縮比:壓縮比越高,壓縮后文件越小,所以壓縮比越高越好。 壓縮時(shí)間:越快越好。 已經(jīng)壓縮的格式文件是否可以再分割:可以分割的格式允許單一文件由多個(gè)Mapper程序處理,可以更好的并行化。 - 壓縮模式對(duì)比
BZip2有最高的壓縮比但也會(huì)帶來(lái)更高的CPU開銷,Gzip較BZip2次之。 如果基于磁盤利用率和I/O考慮,這兩個(gè)壓縮算法都是比較有吸引力的算法。 LZO和Snappy算法有更快的解壓縮速度,如果更關(guān)注壓縮、解壓速度,它們都是不錯(cuò)的選擇。 LZO和Snappy在壓縮數(shù)據(jù)上的速度大致相當(dāng),但Snappy算法在解壓速度上要較LZO更快。 Hadoop的會(huì)將大文件分割成HDFS block(默認(rèn)64MB)大小的splits分片,每個(gè)分片對(duì)應(yīng)一個(gè)Mapper程序。 在這幾個(gè)壓縮算法中 BZip2、LZO、Snappy壓縮是可分割的,Gzip則不支持分割。
Hive的安裝與使用
當(dāng)前版本請(qǐng)閱讀以下參考資料,后期再行完善
- hive的安裝和使用
- Hive入門及常用指令
- 更多進(jìn)階內(nèi)容請(qǐng)自行百度拓展查閱
如何在Hive中集成HBase
- 將Hbase的客戶端
jar拷貝至Hive/lib目錄下 - 修改
hive/conf下的hive-site.xml配置文件,添加如下屬性:<poperty> <name>hbase.zookeeper.quorum</name> <value>hadoop</value> </poperty> - 啟動(dòng)Hive,創(chuàng)建表管理表
hbase_table_1,指定數(shù)據(jù)存儲(chǔ)在Hbase表中,主要是通過(guò)stored by HBaseStorageHandler類來(lái)實(shí)現(xiàn) - 往Hive表
hbase_table_1表中插入數(shù)據(jù)
如何通過(guò) HiveSQL 來(lái)直接讀寫 HBase
當(dāng)前版本請(qǐng)閱讀以下參考資料,后期再行完善
- 如何整合hive和hbase
- HiveHbase集成實(shí)踐
- 更多進(jìn)階內(nèi)容請(qǐng)自行百度拓展查閱
Hive的分區(qū)和分桶
Hive的分區(qū)分桶都是數(shù)據(jù)存儲(chǔ)和組織的策略,分區(qū)類似文件的分類歸檔,分桶類似于傳統(tǒng)數(shù)據(jù)庫(kù)的索引
什么是Hive分區(qū)
- Hive中數(shù)據(jù)庫(kù),表,及分區(qū)都是在HDFS存儲(chǔ)的一個(gè)抽象
- Hive中的一個(gè)分區(qū)對(duì)應(yīng)的就是HDFS的一個(gè)目錄,目錄名就是分區(qū)字段
- 聲明分區(qū)表
PARTITIONED BY (name string),分區(qū)鍵不能和任何列重名 - 聲明數(shù)據(jù)要導(dǎo)入的分區(qū)
PARTITION(name="fx67ll") - 查看分區(qū)
SHOW PARTITIONAS - 根據(jù)分區(qū)查詢
WHERE name = "fx67ll" - 指定切分格式
ROW FORMAT DELIMITED # 每個(gè)字段之間由[ , ]分割 FIELDS TERMINATED BY ',' # 字段是Array形式,元素與元素之間由[ - ]分割 COLLECTION ITEMS TERMINATED BY '-' # 字段是K-V形式,每組K-V對(duì)內(nèi)部由[ : ]分割 MAP KEYS TERMINATED BY ':';
Hive分區(qū)的優(yōu)點(diǎn)
- 如果一個(gè)表中有大量的數(shù)據(jù),我們?nèi)磕贸鰜?lái)做查詞的功能,耗時(shí)比較長(zhǎng),查詢較慢,
使用了分區(qū),就可以做到用到了那個(gè)分區(qū)就拿那個(gè)分區(qū)中的數(shù)據(jù)方便了查詢,提高了查詞的效率 - 橫向分配數(shù)據(jù),使得負(fù)載更為均衡
Hive分區(qū)的缺點(diǎn)
- 容易造成過(guò)多的小分區(qū),過(guò)多的目錄
- 如果分區(qū)策略不佳,容易導(dǎo)致分區(qū)數(shù)據(jù)不均衡,造成數(shù)據(jù)傾斜
什么是Hive分桶
- 分桶是相對(duì)分區(qū)進(jìn)行更細(xì)粒度的劃分,分桶將整個(gè)數(shù)據(jù)內(nèi)容按照某列屬性值得hash值進(jìn)行區(qū)分,類似于關(guān)系型數(shù)據(jù)的索引
- 如要安裝id屬性分為3個(gè)桶,就是對(duì)id屬性值的hash值對(duì)3取摸,按照取模結(jié)果對(duì)數(shù)據(jù)分桶,
如取模結(jié)果為0的數(shù)據(jù)記錄存放到一個(gè)文件,取模為1的數(shù)據(jù)存放到一個(gè)文件,取模為2的數(shù)據(jù)存放到一個(gè)文件 - 分桶之前要執(zhí)行命令
set hive.enforce.bucketing = true - 聲明分桶表
CLUSTERED BY(id) INTO 3 BUCKETS
關(guān)于Hive索引的說(shuō)明
- 即從3.0開始索引已經(jīng)被移除,有一些可替代的方案可能與索引類似:
- 具有自動(dòng)重寫的物化視圖可以產(chǎn)生非常相似的結(jié)果,Hive2.3.0增加了對(duì)物化視圖視圖的支持
- 使用列式文件格式((Parquet、ORC)–他們可以進(jìn)行選擇性掃描;甚至可以跳過(guò)整個(gè)文件/塊。很顯然,例如我們創(chuàng)建表時(shí)使用的ORC格式就已經(jīng)具有了索引的功能
- Hive為什么刪除了索引:
- 由于Hive是針對(duì)海量數(shù)據(jù)存儲(chǔ)的,創(chuàng)建索引需要占用大量的空間,最主要的是Hive索引無(wú)法自動(dòng)進(jìn)行刷新,也就是當(dāng)新的數(shù)據(jù)加入時(shí)候,無(wú)法為這些數(shù)據(jù)自動(dòng)加入索引
Hive分桶的優(yōu)點(diǎn)
- 分桶字段需要根據(jù)業(yè)務(wù)進(jìn)行設(shè)定,可以解決數(shù)據(jù)傾斜問(wèn)題,主要是在關(guān)聯(lián)join的時(shí)候通過(guò)map端更快的連接
- 能夠提供類似的哈希的快速響應(yīng),比分區(qū)更快
Hive分桶的缺點(diǎn)
- 需要在建表時(shí)規(guī)劃好分桶策略,需要手動(dòng)加載數(shù)據(jù)到分桶表
- 本質(zhì)是空間換時(shí)間,時(shí)間換效率,所以在加載數(shù)據(jù)到表的時(shí)候有空間和時(shí)間上的消耗
Hive中靜態(tài)分區(qū)和動(dòng)態(tài)分區(qū)的區(qū)別
- 靜態(tài)分區(qū)與動(dòng)態(tài)分區(qū)的主要區(qū)別在于靜態(tài)分區(qū)是手動(dòng)指定,而動(dòng)態(tài)分區(qū)是通過(guò)數(shù)據(jù)來(lái)進(jìn)行判斷
- 詳細(xì)來(lái)說(shuō),靜態(tài)分區(qū)的列實(shí)在編譯時(shí)期,通過(guò)用戶傳遞來(lái)決定的;動(dòng)態(tài)分區(qū)只有在SQL執(zhí)行時(shí)才能決定
- 查詢和寫入的時(shí)候,靜態(tài)分區(qū)鍵要用
<static partition key> = <value>指定分區(qū)值;動(dòng)態(tài)分區(qū)只需要給出分出分區(qū)鍵名稱<dynamic partition key> - 一張表可同時(shí)被靜態(tài)和動(dòng)態(tài)分區(qū)鍵分區(qū),只是動(dòng)態(tài)分區(qū)鍵需要放在靜態(tài)分區(qū)建的后面,因?yàn)镠DFS上的動(dòng)態(tài)分區(qū)目錄下不能包含靜態(tài)分區(qū)的子目錄
Hive動(dòng)態(tài)分區(qū)的參數(shù)設(shè)定
- 開啟動(dòng)態(tài)分區(qū)
# 開啟動(dòng)態(tài)分區(qū)功能,默認(rèn)false set hive.exec.dynamic.partition = true # 允許所有分區(qū)都是動(dòng)態(tài)的,否則必須有靜態(tài)分區(qū)字段,默認(rèn)strict set hive.exec.dynamic.partition.mode = nonstrict - 動(dòng)態(tài)分區(qū)參數(shù)調(diào)優(yōu)
# 每個(gè)mapper或reducer可以允許創(chuàng)建的最大動(dòng)態(tài)分區(qū)個(gè)數(shù),默認(rèn)是100,超出則會(huì)報(bào)錯(cuò) set hive.exec.max.dynamic.partitions.pernode = 1000 # 一個(gè)動(dòng)態(tài)分區(qū)語(yǔ)句可以創(chuàng)建的最大動(dòng)態(tài)分區(qū)個(gè)數(shù),默認(rèn)是1000,超出報(bào)錯(cuò) set hive.exec.max.dynamic.partitions = 10000 # 全局可以創(chuàng)建的最大文件個(gè)數(shù),默認(rèn)是10000,超出報(bào)錯(cuò) set hive.exec.max.created.files =100000
Hive的內(nèi)部表和外部表
什么是Hive的內(nèi)部表和外部表
- 沒(méi)有
external修飾,表數(shù)據(jù)保存在Hive默認(rèn)的路徑下,數(shù)據(jù)完全由Hive管理,刪除表時(shí)元數(shù)據(jù)(metadata)和表數(shù)據(jù)都會(huì)一起刪除 - 有
external修飾,表數(shù)據(jù)保存在HDFS上,該位置由用戶指定,刪除表時(shí),只會(huì)刪除表的元數(shù)據(jù)(metadata)
Hive內(nèi)部表和外部表的區(qū)別是什么
- 內(nèi)部表數(shù)據(jù)由Hive自身管理,外部表數(shù)據(jù)由HDFS管理
- 內(nèi)部表數(shù)據(jù)存儲(chǔ)的位置是
hive.metastore.warehouse.dir,默認(rèn)是/user/hive/warehouse - 外部表數(shù)據(jù)的存儲(chǔ)位置由自己制定,如果沒(méi)有LOCATION,Hive將在HDFS上的
/user/hive/warehouse文件夾下以外部表的表名創(chuàng)建一個(gè)文件夾,并將屬于這個(gè)表的數(shù)據(jù)存放在這里 - 刪除內(nèi)部表會(huì)直接刪除元數(shù)據(jù)(metadata)及存儲(chǔ)數(shù)據(jù)
- 刪除外部表僅僅會(huì)刪除元數(shù)據(jù)(metadata),HDFS上的文件并不會(huì)被刪除
- 對(duì)內(nèi)部表的修改會(huì)將修改直接同步給元數(shù)據(jù)(metadata),而對(duì)外部表的表結(jié)構(gòu)和分區(qū)進(jìn)行修改,則需要修復(fù)
MSCK REPAIR TABLE table_name
生產(chǎn)環(huán)境中為什么建議使用外部表
- 因?yàn)橥獠勘聿粫?huì)加載數(shù)據(jù)到Hive,減少數(shù)據(jù)傳輸,數(shù)據(jù)還能共享
- Hive不會(huì)修改數(shù)據(jù),所以無(wú)需擔(dān)心數(shù)據(jù)的損壞
- 刪除表時(shí),只刪除表結(jié)構(gòu),不刪除數(shù)據(jù)
Hive SQL
Hive中的SQL如何轉(zhuǎn)化成MapReduce任務(wù)的
-
Antlr定義SQL的語(yǔ)法規(guī)則,完成SQL詞法,語(yǔ)法解析,將SQL轉(zhuǎn)化為抽象語(yǔ)法樹 - 遍歷抽象語(yǔ)法樹抽象出查詢的基本組成單元
QueryBlock - 遍歷
QueryBlock,翻譯為執(zhí)行操作樹OperatorTree - 邏輯層優(yōu)化器進(jìn)行
OperatorTree變換,合并不必要的ReduceSinkOperator,減少shuffle數(shù)據(jù)量 - 遍厲
OperatorTree,翻譯為MapReduce任務(wù) - 物理層優(yōu)化器進(jìn)行
MapReduce任務(wù)的變換,生成最終的執(zhí)行計(jì)劃
什么情況下Hive不走M(jìn)apReduce任務(wù)
Hive中如何查詢A表中B表不存在的數(shù)據(jù)
題目:A、B兩表,找出ID字段中,存在A表,但是不存在B表的數(shù)據(jù)。A表總共13w數(shù)據(jù),去重后大約3W條數(shù)據(jù),B表有2W條數(shù)據(jù),且B表的ID字段有索引
select * from B
where (select count(1) as num from A where A.ID = B.ID) = 0
Hive中有哪些連接查詢以及如何使用
當(dāng)前版本請(qǐng)閱讀以下參考資料,后期再行完善
- Hive——join的使用
- 更多進(jìn)階內(nèi)容請(qǐng)自行百度拓展查閱
Hive中左連接和內(nèi)連接的區(qū)別
- 內(nèi)連接:連接的鍵匹配上就連接,沒(méi)有匹配上就過(guò)濾掉
- 左連接:以左表為基準(zhǔn),與右表做關(guān)聯(lián),關(guān)聯(lián)上則連接,右表關(guān)聯(lián)不上的則為null
Hive中左連接的底層原理
參考下面Hive查詢的時(shí)候on和where有什么區(qū)別的理解二
Hive查詢的時(shí)候 ON 和 WHERE 有什么區(qū)別
共同點(diǎn)
- on先執(zhí)行,where后執(zhí)行
- 并且where是對(duì)連接之后的結(jié)果進(jìn)行的查詢條件
第一種理解方式
- 條件不為主表?xiàng)l件的時(shí)候,放在on和where的后面一樣
- 條件為主表?xiàng)l件的時(shí)候,放在on后面,結(jié)果為主表全量,放在where后面的時(shí)候?yàn)橹鞅項(xiàng)l件篩選過(guò)后的全量
1. select * from a left join b on a.id = b.id and a.dt=20181115;
2. select * from a left join b on a.id = b.id and b.dt=20181115;
3. select * from a join b on a.id = b.id and a.dt=20181115;
4. select * from a left join b on a.id = b.id where a.dt=20181115;
sql1: 如果是left join 在on上寫主表a的條件不會(huì)生效,全表掃描。
sql2: 如果是left join 在on上寫副表b的條件會(huì)生效,但是語(yǔ)義與寫到where 條件不同
sql3: 如果是inner join 在on上寫主表a、副表b的條件都會(huì)生效
sql4: 建議這么寫,大家寫sql大部分的語(yǔ)義都是先過(guò)濾數(shù)據(jù)然后再join,所以在不了解join on+條件的情況下,條件盡量別寫在on后,
直接寫到where后就ok了,如果where條件后寫b表的過(guò)濾條件,就變成了先left join出結(jié)果再按照b條件過(guò)濾數(shù)據(jù)
第二種理解方式
-
on是在生成連接表的起作用的,where是生成連接表之后對(duì)連接表再進(jìn)行過(guò)濾 - 當(dāng)使用
left join時(shí),無(wú)論on的條件是否滿足,都會(huì)返回左表的所有記錄,對(duì)于滿足的條件的記錄,兩個(gè)表對(duì)應(yīng)的記錄會(huì)連接起來(lái),對(duì)于不滿足條件的記錄,那右表字段全部是null - 當(dāng)使用
right join時(shí),類似,只不過(guò)是全部返回右表的所有記錄 - 當(dāng)使用
inner join時(shí),功能與where完全相同
經(jīng)過(guò)親測(cè)后,更加深了對(duì)on和where的理解,得出以下結(jié)論:
1.ON后的條件如果有過(guò)濾主表的條件,則結(jié)果對(duì)于不符合該條件的主表數(shù)據(jù)也會(huì)原條數(shù)保留,只是不匹配右表數(shù)據(jù)而已。對(duì)于on后面對(duì)右表的過(guò)濾條件,連接時(shí)會(huì)用該條件直接過(guò)濾右表數(shù)據(jù)后再和左邊進(jìn)行左連接??傊?,對(duì)于不滿足on后面的所有條件的數(shù)據(jù),左表會(huì)在結(jié)果數(shù)據(jù)中原條數(shù)保留數(shù)據(jù),只是不匹配右表數(shù)據(jù)而已。不滿足條件的右表數(shù)據(jù)各字段會(huì)直接以NULL連接主表。
2.ON后對(duì)左表的篩選條件對(duì)于結(jié)果行數(shù)會(huì)被忽略,但會(huì)影響結(jié)果中的匹配右表數(shù)據(jù),因?yàn)橹挥蟹献蟊項(xiàng)l件的數(shù)據(jù)才會(huì)去和符合條件的右表數(shù)據(jù)進(jìn)行匹配,不符合條件的左表數(shù)據(jù)會(huì)保留在最后結(jié)果中,但匹配的右表數(shù)據(jù)都是NULL.因此,對(duì)于需要過(guò)濾左表數(shù)據(jù)的話,需要把過(guò)濾條件放到where后面。
3.ON后的左表?xiàng)l件(單獨(dú)對(duì)左表進(jìn)行的篩選條件)對(duì)于結(jié)果行數(shù)無(wú)影響,還是會(huì)返回所有左表的數(shù)據(jù),但和右表匹配數(shù)據(jù)時(shí),系統(tǒng)只會(huì)拿左表符合條件(ON后的對(duì)左表過(guò)濾條件)的數(shù)據(jù)去和右表符合條件(ON后的對(duì)右表過(guò)濾條件)的數(shù)據(jù)進(jìn)行匹配抓取數(shù)據(jù),而不符合條件的左表數(shù)據(jù)還是會(huì)出現(xiàn)在結(jié)果列表中,只是對(duì)應(yīng)的右表數(shù)據(jù)都是NULL。
4.ON后的右表?xiàng)l件(單獨(dú)對(duì)右表進(jìn)行的篩選條件)會(huì)先對(duì)右表進(jìn)行數(shù)據(jù)篩選后再和左表做連接查詢,對(duì)結(jié)果行數(shù)有影響(當(dāng)左表對(duì)右表是一對(duì)多時(shí)),但不會(huì)影響左表的顯示行數(shù),然后拿符合條件的右表數(shù)據(jù)去和符合條件的左表數(shù)據(jù)進(jìn)行匹配。
5.Where還是對(duì)連接后的數(shù)據(jù)進(jìn)行過(guò)濾篩選,這個(gè)無(wú)異議。
6.匹配數(shù)據(jù)時(shí)無(wú)論左右表,都是拿符合ON后的過(guò)濾條件去做數(shù)據(jù)匹配,不符合的會(huì)保留左表數(shù)據(jù),用NULL填充右表數(shù)據(jù)。
綜上得出,ON后面對(duì)于左表的過(guò)濾條件,在最后結(jié)果行數(shù)中會(huì)被忽略,并不會(huì)先去過(guò)濾左表數(shù)據(jù)再連接查詢,但是ON后的右表?xiàng)l件會(huì)先過(guò)濾右表數(shù)據(jù)再連接左表進(jìn)行查詢。
連接查詢時(shí),都是用符合ON后的左右表的過(guò)濾條件的數(shù)據(jù)進(jìn)行連接查詢,只有符合左右表過(guò)濾條件的數(shù)據(jù)才能正確匹配,剩下的左表數(shù)據(jù)會(huì)正常出現(xiàn)在結(jié)果集中,但匹配的右表數(shù)據(jù)是NULL。因此對(duì)于左表的過(guò)濾條件切記要放到Where后,對(duì)于右表的過(guò)濾條件要看情況了。如果需要先過(guò)濾右表數(shù)據(jù)就把條件放到ON后面即可。
Hive 函數(shù)
關(guān)于 UDF/UDAF/UDTF 的提問(wèn)
- 如何使用UDF/UDAF/UDTF
- 為什么使用UDF/UDAF/UDTF
- 你寫過(guò)什么樣的UDF/UDAF/UDTF
- Hive自定義函數(shù)實(shí)現(xiàn)了什么函數(shù)
上述四個(gè)問(wèn)題自行 參考資料 并結(jié)合工作中實(shí)際場(chǎng)景來(lái)作答,沒(méi)有標(biāo)準(zhǔn)答案
Hive中如何去重
第一種方式:使用 DISTINCT
- 對(duì)select 后面所有字段去重,并不能只對(duì)一列去重
- 當(dāng)
DISTINCT應(yīng)用到多個(gè)字段的時(shí)候,DISTINCT必須放在開頭,其應(yīng)用的范圍是其后面的所有字段,而不只是緊挨著它的一個(gè)字段,而且DISTINCT只能放到所有字段的前面 -
DISTINCT對(duì)NULL是不進(jìn)行過(guò)濾的,即返回的結(jié)果中是包含NULL值的 - 聚合函數(shù)中的
DISTINCT,如count()會(huì)過(guò)濾掉為NULL
第二種方式:使用 GROUP BY
- 對(duì)
GROUP BY后面所有字段去重,并不能只對(duì)一列去重
第三種方式:使用 ROW_NUMBER() OVER 窗口函數(shù)
- 參考資料一:一種巧妙的hive sql數(shù)據(jù)去重方法
- 參考資料二:Hive--數(shù)據(jù)去重及row_number()
- 參考資料三:Hive(十一)--數(shù)據(jù)去重及row_number()
Hive中排序函數(shù)的使用方式及區(qū)別
-
order by會(huì)對(duì)輸入做全局排序,為保證全局的排序,因此只有一個(gè)reducer,會(huì)導(dǎo)致當(dāng)輸入規(guī)模較大時(shí),需要較長(zhǎng)的計(jì)算時(shí)間。 -
sort by不是全局排序,其在數(shù)據(jù)進(jìn)入reducer前完成排序。因此,如果用sort by進(jìn)行排序,則sort by只保證每個(gè)reducer的輸出有序,不保證全局有序。 -
distribute by 字段根據(jù)指定的字段將數(shù)據(jù)分到不同的reducer,且分發(fā)算法是hash散列,常用sort by結(jié)合使用,Hive要求distribute by語(yǔ)句要寫在sort by語(yǔ)句之前。 -
cluster by 字段除了具有distribute by的功能(既可以把數(shù)據(jù)分到不同的reduce)外,還會(huì)對(duì)該字段進(jìn)行排序。但是排序只能是倒序排序,不能指定排序規(guī)則為asc或者desc - 因此:
- 當(dāng)數(shù)據(jù)量規(guī)模較大時(shí),不使用
order by,使用用distribute by + sort by - 如果
distribute by和sort by字段是同一個(gè)時(shí),此時(shí),cluster by = distribute by + sort by
- 當(dāng)數(shù)據(jù)量規(guī)模較大時(shí),不使用
Hive中部分高頻函數(shù) ———— split / coalesce / collect list / collect set
Hive常用函數(shù)
Hive 運(yùn)維
如何監(jiān)控一個(gè)提交后的Hive狀態(tài)
- 使用java代碼提交Hive,通過(guò)HiveStatement獲取日志數(shù)據(jù)并解析出
application_id - 就可以通過(guò)
application_id去yarn上查看運(yùn)行狀態(tài)
Hive 優(yōu)化
該模塊請(qǐng)參考我關(guān)于Hive優(yōu)化的文章
- 點(diǎn)擊訪問(wèn) ————> Hive在工作中的調(diào)優(yōu)總結(jié)
- 點(diǎn)擊訪問(wèn) ————> HiveSQL工作實(shí)戰(zhàn)總結(jié)
我是 fx67ll.com,如果您發(fā)現(xiàn)本文有什么錯(cuò)誤,歡迎在評(píng)論區(qū)討論指正,感謝您的閱讀!
如果您喜歡這篇文章,歡迎訪問(wèn)我的 本文github倉(cāng)庫(kù)地址,為我點(diǎn)一顆Star,Thanks~ :)
轉(zhuǎn)發(fā)請(qǐng)注明參考文章地址,非常感謝?。?!