1. Hive內(nèi)部表和外部表的區(qū)別
未被external修飾的是內(nèi)部表,被external修飾的為外部表。
區(qū)別:
內(nèi)部表數(shù)據(jù)由Hive自身管理,外部表數(shù)據(jù)由HDFS管理;
內(nèi)部表數(shù)據(jù)存儲的位置是
hive.metastore.warehouse.dir(默認:/user/hive/warehouse),外部表數(shù)據(jù)的存儲位置由自己制定(如果沒有LOCATION,Hive將在HDFS上的/user/hive/warehouse文件夾下以外部表的表名創(chuàng)建一個文件夾,并將屬于這個表的數(shù)據(jù)存放在這里);刪除內(nèi)部表會直接刪除元數(shù)據(jù)(metadata)及存儲數(shù)據(jù);刪除外部表僅僅會刪除元數(shù)據(jù),HDFS上的文件并不會被刪除。
2. Hive有索引嗎
Hive支持索引(3.0版本之前),但是Hive的索引與關(guān)系型數(shù)據(jù)庫中的索引并不相同,比如,Hive不支持主鍵或者外鍵。并且Hive索引提供的功能很有限,效率也并不高,因此Hive索引很少使用。
- 索引適用的場景:
適用于不更新的靜態(tài)字段。以免總是重建索引數(shù)據(jù)。每次建立、更新數(shù)據(jù)后,都要重建索引以構(gòu)建索引表。
- Hive索引的機制如下:
hive在指定列上建立索引,會產(chǎn)生一張索引表(Hive的一張物理表),里面的字段包括:索引列的值、該值對應(yīng)的HDFS文件路徑、該值在文件中的偏移量。
Hive 0.8版本后引入bitmap索引處理器,這個處理器適用于去重后,值較少的列(例如,某字段的取值只可能是幾個枚舉值) 因為索引是用空間換時間,索引列的取值過多會導(dǎo)致建立bitmap索引表過大。
注意:Hive中每次有數(shù)據(jù)時需要及時更新索引,相當(dāng)于重建一個新表,否則會影響數(shù)據(jù)查詢的效率和準確性,Hive官方文檔已經(jīng)明確表示Hive的索引不推薦被使用,在新版本的Hive中已經(jīng)被廢棄了。
擴展:Hive是在0.7版本之后支持索引的,在0.8版本后引入bitmap索引處理器,在3.0版本開始移除索引的功能,取而代之的是2.3版本開始的物化視圖,自動重寫的物化視圖替代了索引的功能。
3. 運維如何對Hive進行調(diào)度
將hive的sql定義在腳本當(dāng)中;
使用azkaban或者oozie進行任務(wù)的調(diào)度;
監(jiān)控任務(wù)調(diào)度頁面。
4. ORC、Parquet等列式存儲的優(yōu)點
ORC和Parquet都是高性能的存儲方式,這兩種存儲格式總會帶來存儲和性能上的提升。
Parquet:
Parquet支持嵌套的數(shù)據(jù)模型,類似于Protocol Buffers,每一個數(shù)據(jù)模型的schema包含多個字段,每一個字段有三個屬性:重復(fù)次數(shù)、數(shù)據(jù)類型和字段名。
重復(fù)次數(shù)可以是以下三種:required(只出現(xiàn)1次),repeated(出現(xiàn)0次或多次),optional(出現(xiàn)0次或1次)。每一個字段的數(shù)據(jù)類型可以分成兩種: group(復(fù)雜類型)和primitive(基本類型)。Parquet中沒有Map、Array這樣的復(fù)雜數(shù)據(jù)結(jié)構(gòu),但是可以通過repeated和group組合來實現(xiàn)的。
由于Parquet支持的數(shù)據(jù)模型比較松散,可能一條記錄中存在比較深的嵌套關(guān)系,如果為每一條記錄都維護一個類似的樹狀結(jié)可能會占用較大的存儲空間,因此Dremel論文中提出了一種高效的對于嵌套數(shù)據(jù)格式的壓縮算法:Striping/Assembly算法。通過Striping/Assembly算法,parquet可以使用較少的存儲空間表示復(fù)雜的嵌套格式,并且通常Repetition level和Definition level都是較小的整數(shù)值,可以通過RLE算法對其進行壓縮,進一步降低存儲空間。
Parquet文件是以二進制方式存儲的,是不可以直接讀取和修改的,Parquet文件是自解析的,文件中包括該文件的數(shù)據(jù)和元數(shù)據(jù)。
ORC:
ORC文件是自描述的,它的元數(shù)據(jù)使用Protocol Buffers序列化,并且文件中的數(shù)據(jù)盡可能的壓縮以降低存儲空間的消耗。
和Parquet類似,ORC文件也是以二進制方式存儲的,所以是不可以直接讀取,ORC文件也是自解析的,它包含許多的元數(shù)據(jù),這些元數(shù)據(jù)都是同構(gòu)ProtoBuffer進行序列化的。
ORC會盡可能合并多個離散的區(qū)間盡可能的減少I/O次數(shù)。
ORC中使用了更加精確的索引信息,使得在讀取數(shù)據(jù)時可以指定從任意一行開始讀取,更細粒度的統(tǒng)計信息使得讀取ORC文件跳過整個row group,ORC默認會對任何一塊數(shù)據(jù)和索引信息使用ZLIB壓縮,因此ORC文件占用的存儲空間也更小。
在新版本的ORC中也加入了對Bloom Filter的支持,它可以進一 步提升謂詞下推的效率,在Hive 1.2.0版本以后也加入了對此的支 持。
5. 數(shù)據(jù)建模用的哪些模型?
1. 星型模型

星形模式(Star Schema)是最常用的維度建模方式。星型模式是以事實表為中心,所有的維度表直接連接在事實表上,像星星一樣。 星形模式的維度建模由一個事實表和一組維表成,且具有以下特點:
a. 維表只和事實表關(guān)聯(lián),維表之間沒有關(guān)聯(lián);
b. 每個維表主鍵為單列,且該主鍵放置在事實表中,作為兩邊連接的外鍵;
c. 以事實表為核心,維表圍繞核心呈星形分布。
2. 雪花模型

雪花模式(Snowflake Schema)是對星形模式的擴展。雪花模式的維度表可以擁有其他維度表的,雖然這種模型相比星型更規(guī)范一些,但是由于這種模型不太容易理解,維護成本比較高,而且性能方面需要關(guān)聯(lián)多層維表,性能比星型模型要低。
3. 星座模型

星座模式是星型模式延伸而來,星型模式是基于一張事實表的,而星座模式是基于多張事實表的,而且共享維度信息。前面介紹的兩種維度建模方法都是多維表對應(yīng)單事實表,但在很多時候維度空間內(nèi)的事實表不止一個,而一個維表也可能被多個事實表用到。在業(yè)務(wù)發(fā)展后期,絕大部分維度建模都采用的是星座模式。
數(shù)倉建模詳細介紹可查看:通俗易懂?dāng)?shù)倉建模
6. 為什么要對數(shù)據(jù)倉庫分層?
用空間換時間,通過大量的預(yù)處理來提升應(yīng)用系統(tǒng)的用戶體驗(效率),因此數(shù)據(jù)倉庫會存在大量冗余的數(shù)據(jù)。
如果不分層的話,如果源業(yè)務(wù)系統(tǒng)的業(yè)務(wù)規(guī)則發(fā)生變化將會影響整個數(shù)據(jù)清洗過程,工作量巨大。
通過數(shù)據(jù)分層管理可以簡化數(shù)據(jù)清洗的過程,因為把原來一步的工作分到了多個步驟去完成,相當(dāng)于把一個復(fù)雜的工作拆成了多個簡單的工作,把一個大的黑盒變成了一個白盒,每一層的處理邏輯都相對簡單和容易理解,這樣我們比較容易保證每一個步驟的正確性,當(dāng)數(shù)據(jù)發(fā)生錯誤的時候,往往我們只需要局部調(diào)整某個步驟即可。
數(shù)據(jù)倉庫詳細介紹可查看:萬字詳解整個數(shù)據(jù)倉庫建設(shè)體系
7. 使用過Hive解析JSON串嗎
Hive處理json數(shù)據(jù)總體來說有兩個方向的路走:
將json以字符串的方式整個入Hive表,然后通過使用UDF函數(shù)解析已經(jīng)導(dǎo)入到hive中的數(shù)據(jù),比如使用
LATERAL VIEW json_tuple的方法,獲取所需要的列名。在導(dǎo)入之前將json拆成各個字段,導(dǎo)入Hive表的數(shù)據(jù)是已經(jīng)解析過的。這將需要使用第三方的 SerDe。
詳細介紹可查看:Hive解析Json數(shù)組超全講解
8. sort by 和 order by 的區(qū)別
order by 會對輸入做全局排序,因此只有一個reducer(多個reducer無法保證全局有序)只有一個reducer,會導(dǎo)致當(dāng)輸入規(guī)模較大時,需要較長的計算時間。
sort by不是全局排序,其在數(shù)據(jù)進入reducer前完成排序. 因此,如果用sort by進行排序,并且設(shè)置mapred.reduce.tasks>1, 則sort by只保證每個reducer的輸出有序,不保證全局有序。
9. 數(shù)據(jù)傾斜怎么解決
數(shù)據(jù)傾斜問題主要有以下幾種:
空值引發(fā)的數(shù)據(jù)傾斜
不同數(shù)據(jù)類型引發(fā)的數(shù)據(jù)傾斜
不可拆分大文件引發(fā)的數(shù)據(jù)傾斜
數(shù)據(jù)膨脹引發(fā)的數(shù)據(jù)傾斜
表連接時引發(fā)的數(shù)據(jù)傾斜
確實無法減少數(shù)據(jù)量引發(fā)的數(shù)據(jù)傾斜
以上傾斜問題的具體解決方案可查看:Hive千億級數(shù)據(jù)傾斜解決方案
注意:對于 left join 或者 right join 來說,不會對關(guān)聯(lián)的字段自動去除null值,對于 inner join 來說,會對關(guān)聯(lián)的字段自動去除null值。
小伙伴們在閱讀時注意下,在上面的文章(Hive千億級數(shù)據(jù)傾斜解決方案)中,有一處sql出現(xiàn)了上述問題(舉例的時候原本是想使用left join的,結(jié)果手誤寫成了join)。此問題由公眾號讀者發(fā)現(xiàn),感謝這位讀者指正。
10. Hive 小文件過多怎么解決
1. 使用 hive 自帶的 concatenate 命令,自動合并小文件
使用方法:
#對于非分區(qū)表alter table A concatenate;#對于分區(qū)表alter table B partition(day=20201224) concatenate;
注意:
1、concatenate 命令只支持 RCFILE 和 ORC 文件類型。
2、使用concatenate命令合并小文件時不能指定合并后的文件數(shù)量,但可以多次執(zhí)行該命令。
3、當(dāng)多次使用concatenate后文件數(shù)量不在變化,這個跟參數(shù) mapreduce.input.fileinputformat.split.minsize=256mb 的設(shè)置有關(guān),可設(shè)定每個文件的最小size。
2. 調(diào)整參數(shù)減少Map數(shù)量
設(shè)置map輸入合并小文件的相關(guān)參數(shù)(執(zhí)行Map前進行小文件合并):
在mapper中將多個文件合成一個split作為輸入(CombineHiveInputFormat底層是Hadoop的CombineFileInputFormat方法):
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; -- 默認
每個Map最大輸入大小(這個值決定了合并后文件的數(shù)量):
set mapred.max.split.size=256000000; -- 256M
一個節(jié)點上split的至少大?。ㄟ@個值決定了多個DataNode上的文件是否需要合并):
set mapred.min.split.size.per.node=100000000; -- 100M
一個交換機下split的至少大小(這個值決定了多個交換機上的文件是否需要合并):
set mapred.min.split.size.per.rack=100000000; -- 100M
3. 減少Reduce的數(shù)量
reduce 的個數(shù)決定了輸出的文件的個數(shù),所以可以調(diào)整reduce的個數(shù)控制hive表的文件數(shù)量。
hive中的分區(qū)函數(shù) distribute by 正好是控制MR中partition分區(qū)的,可以通過設(shè)置reduce的數(shù)量,結(jié)合分區(qū)函數(shù)讓數(shù)據(jù)均衡的進入每個reduce即可:
#設(shè)置reduce的數(shù)量有兩種方式,第一種是直接設(shè)置reduce個數(shù)set mapreduce.job.reduces=10;#第二種是設(shè)置每個reduce的大小,Hive會根據(jù)數(shù)據(jù)總大小猜測確定一個reduce個數(shù)set hive.exec.reducers.bytes.per.reducer=5120000000; -- 默認是1G,設(shè)置為5G#執(zhí)行以下語句,將數(shù)據(jù)均衡的分配到reduce中set mapreduce.job.reduces=10;insert overwrite table A partition(dt)select * from Bdistribute by rand();
對于上述語句解釋:如設(shè)置reduce數(shù)量為10,使用 rand(), 隨機生成一個數(shù) x % 10 , 這樣數(shù)據(jù)就會隨機進入 reduce 中,防止出現(xiàn)有的文件過大或過小。
4. 使用hadoop的archive將小文件歸檔
Hadoop Archive簡稱HAR,是一個高效地將小文件放入HDFS塊中的文件存檔工具,它能夠?qū)⒍鄠€小文件打包成一個HAR文件,這樣在減少namenode內(nèi)存使用的同時,仍然允許對文件進行透明的訪問。
#用來控制歸檔是否可用set hive.archive.enabled=true;#通知Hive在創(chuàng)建歸檔時是否可以設(shè)置父目錄set hive.archive.har.parentdir.settable=true;#控制需要歸檔文件的大小set har.partfile.size=1099511627776;使用以下命令進行歸檔:ALTER TABLE A ARCHIVE PARTITION(dt='2021-05-07', hr='12');對已歸檔的分區(qū)恢復(fù)為原文件:ALTER TABLE A UNARCHIVE PARTITION(dt='2021-05-07', hr='12');
注意:
歸檔的分區(qū)可以查看不能 insert overwrite,必須先 unarchive
Hive 小文件問題具體可查看:解決hive小文件過多問題
11. Hive優(yōu)化有哪些
1. 數(shù)據(jù)存儲及壓縮:
針對hive中表的存儲格式通常有orc和parquet,壓縮格式一般使用snappy。相比與textfile格式表,orc占有更少的存儲。因為hive底層使用MR計算架構(gòu),數(shù)據(jù)流是hdfs到磁盤再到hdfs,而且會有很多次,所以使用orc數(shù)據(jù)格式和snappy壓縮策略可以降低IO讀寫,還能降低網(wǎng)絡(luò)傳輸量,這樣在一定程度上可以節(jié)省存儲,還能提升hql任務(wù)執(zhí)行效率;
2. 通過調(diào)參優(yōu)化:
并行執(zhí)行,調(diào)節(jié)parallel參數(shù);
調(diào)節(jié)jvm參數(shù),重用jvm;
設(shè)置map、reduce的參數(shù);開啟strict mode模式;
關(guān)閉推測執(zhí)行設(shè)置。
3. 有效地減小數(shù)據(jù)集將大表拆分成子表;結(jié)合使用外部表和分區(qū)表。
4. SQL優(yōu)化
大表對大表:盡量減少數(shù)據(jù)集,可以通過分區(qū)表,避免掃描全表或者全字段;
大表對小表:設(shè)置自動識別小表,將小表放入內(nèi)存中去執(zhí)行。
Hive優(yōu)化詳細剖析可查看:Hive企業(yè)級性能優(yōu)化
12. Tez引擎優(yōu)點?
Tez可以將多個有依賴的作業(yè)轉(zhuǎn)換為一個作業(yè),這樣只需寫一次HDFS,且中間節(jié)點較少,從而大大提升作業(yè)的計算性能。
Mr/tez/spark區(qū)別:
Mr引擎:多job串聯(lián),基于磁盤,落盤的地方比較多。雖然慢,但一定能跑出結(jié)果。一般處理,周、月、年指標。
Spark引擎:雖然在Shuffle過程中也落盤,但是并不是所有算子都需要Shuffle,尤其是多算子過程,中間過程不落盤 DAG有向無環(huán)圖。 兼顧了可靠性和效率。一般處理天指標。
Tez引擎:完全基于內(nèi)存。 注意:如果數(shù)據(jù)量特別大,慎重使用。容易OOM。一般用于快速出結(jié)果,數(shù)據(jù)量比較小的場景。