1、什么是Hive,為什么要用Hive,你是如何理解Hive?
Hive是基于Hadoop的一個數(shù)據(jù)倉庫工具,可以將結構化的數(shù)據(jù)文件映射為一張數(shù)據(jù)庫表,并提供類SQL查詢功能(HQL)?!窰ive本質(zhì)是將SQL轉(zhuǎn)換為MapReduce的任務進行運算?!?/p>
個人理解:hive存的是和hdfs的映射關系,hive是邏輯上的數(shù)據(jù)倉庫,實際操作的都是hdfs上的文件,HQL就是用sql語法來寫的mr程序。
2、介紹一下Hive架構

·?Hive可以通過CLI,JDBC和 ODBC 等客戶端進行訪問。除此之外,Hive還支持 WUI 訪問
·?Hive內(nèi)部執(zhí)行流程:解析器(解析SQL語句)、編譯器(把SQL語句編譯成MapReduce程序)、優(yōu)化器(優(yōu)化MapReduce程序)、執(zhí)行器(將MapReduce程序運行的結果提交到HDFS)
·?Hive的「元數(shù)據(jù)」保存在數(shù)據(jù)庫中,如保存在MySQL,SQLServer,PostgreSQL,Oracle及Derby等數(shù)據(jù)庫中。Hive中的元數(shù)據(jù)信息包含表名,列名,分區(qū)及其屬性,表的屬性(包括是否為外部表),表數(shù)據(jù)所在目錄等。
·?Hive將大部分 HiveSQL語句轉(zhuǎn)化為MapReduce作業(yè)提交到Hadoop上執(zhí)行;少數(shù)HiveSQL語句不會轉(zhuǎn)化為MapReduce作業(yè),直接從DataNode上獲取數(shù)據(jù)后按照順序輸出。
3、SQL轉(zhuǎn)化為MapReduce的過程,整個編譯過程分為六個階段:

1、Antlr定義SQL的語法規(guī)則,完成SQL詞法,語法解析,將SQL轉(zhuǎn)化為抽象語法樹AST Tree
2、遍歷AST Tree,抽象出查詢的基本組成單元QueryBlock
3、遍歷QueryBlock,翻譯為執(zhí)行操作樹OperatorTree
4、邏輯層優(yōu)化器進行OperatorTree變換,合并不必要的ReduceSinkOperator,減少shuw le數(shù)據(jù)量
5、遍歷OperatorTree,翻譯為MapReduce任務
6、物理層優(yōu)化器進行MapReduce任務的變換,生成最終的執(zhí)行計劃
4、Hive和數(shù)據(jù)庫比較
Hive 和 數(shù)據(jù)庫 實際上并沒有可比性,除了擁有類似的查詢語言,再無類似之處。
·?數(shù)據(jù)存儲位置
Hive 存儲在HDFS,數(shù)據(jù)庫將數(shù)據(jù)保存在塊設備或者本地文件系統(tǒng)中。
·?數(shù)據(jù)更新
Hive中不建議對數(shù)據(jù)的改寫,而數(shù)據(jù)庫中的數(shù)據(jù)通常是需要經(jīng)常進行修改的。
·?執(zhí)行延遲
Hive 執(zhí)行延遲較高。數(shù)據(jù)庫的執(zhí)行延遲較低。當然,這個是有條件的,即數(shù)據(jù)規(guī)模較小,當數(shù)據(jù)規(guī)模大到超過數(shù)據(jù)庫的處理能力的時候,Hive的并行計算顯然能體現(xiàn)出優(yōu)勢。
·?數(shù)據(jù)規(guī)模
Hive支持很大規(guī)模的數(shù)據(jù)計算;數(shù)據(jù)庫可以支持的數(shù)據(jù)規(guī)模較小。
5、內(nèi)部表和外部表的區(qū)別,以及各自的使用場景
·?內(nèi)部表
如果Hive中沒有特別指定,則默認創(chuàng)建的表都是「管理表」,也稱「內(nèi)部表」。由Hive負責管理表中的數(shù)據(jù),管理表不共享數(shù)據(jù)。刪除管理表時,會刪除管理表中的數(shù)據(jù)和元數(shù)據(jù)信息。
·?外部表
當一份數(shù)據(jù)需要「被共享」時,可以創(chuàng)建一個「外部表」指向這份數(shù)據(jù)。
刪除該表并不會刪除掉原始數(shù)據(jù),刪除的是表的元數(shù)據(jù)。當表結構或者分區(qū)數(shù)發(fā)生變化時,需要進行一步修復的操作。
6、4個By區(qū)別
·?Sort By:分區(qū)內(nèi)有序
·?Order By:全局排序,只有一個Reducer
·?Distrbute By:類似MR中Partition,進行分區(qū),結合sort by使用
·?Cluster By:當Distribute by和Sorts by字段相同時,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外還兼具Sort by的功能。但是排序只能是升序排序,不能指定排序規(guī)則為ASC或者DESC。
7、系統(tǒng)函數(shù)(了解和使用過哪些Hive函數(shù))
1)date_add、date_sub函數(shù)(加減日期)
2)next_day函數(shù)(返回輸入日期開始,緊隨其后的指定星期對應的日期)
3)date_format函數(shù)(根據(jù)格式整理日期)
4)last_day函數(shù)(求當月最后一天日期)
5)列轉(zhuǎn)行:
CONCAT:
返回結果為連接參數(shù)產(chǎn)生的字符串。如有任何一個參數(shù)為NULL?,則返回值為?NULL。
CONCAT_WS:
contcat_ws()?代表?CONCAT?With?Separator?,是CONCAT()的特殊形式。第一個參數(shù)是其它參數(shù)的分隔符。分隔符的位置放在要連接的兩個字符串之間。分隔符可以是一個字符串,也可以是其它參數(shù)。
注意:
如果分隔符為?NULL,則結果為?NULL。函數(shù)會忽略任何分隔符參數(shù)后的?NULL?值。
COLLECT_SET:它們都是將分組中的某列轉(zhuǎn)為一個數(shù)組返回
6)行轉(zhuǎn)列
EXPLODE?
用法:lateral view udtf(expression) tableAlias AS columnAlias
- lateral view:橫向視圖,用于從UDTF生成的表中選擇數(shù)據(jù)。
- udtf(expression):定義UDTF,并使用表達式作為參數(shù)傳遞。
- tableAlias:表示UDTF生成的表的別名。
- columnAlias:表示UDTF生成的表中的列別名。
7)get_json_object解析json函數(shù)
8)NVL(表達式1,表達式2)
如果表達式1為空值,NVL返回值為表達式2的值,否則返回表達式1的值。
8、Hive窗口函數(shù)的區(qū)別
·?RANK() 排序相同時會重復,總數(shù)不會變,例如1224
·?DENSE_RANK() 排序相同時會重復,總數(shù)會減少,例如?1223
·?ROW_NUMBER() 會根據(jù)順序去計算,例如?1234
9、自定義UDF、UDTF函數(shù)
在項目中是否自定義過UDF、UDTF函數(shù),以及用他們處理了什么問題,及自定義步驟?
你可以這么回答:
<1> 自定義過
<2> 我一般用UDF函數(shù)解析公共字段;用UDTF函數(shù)解析事件字段
具體的步驟對應如下:
「自定義UDF」:繼承UDF,重寫evaluate方法
「自定義UDTF」:繼承自GenericUDTF,重寫3個方法:initialize(自定義輸出的列名和類型),process(將結果返回forward(result)),close
為什么要自定義UDF/UDTF?
因為自定義函數(shù),可以自己埋點Log打印日志,出錯或者數(shù)據(jù)異常,方便調(diào)試
10、Hive優(yōu)化
當被問到優(yōu)化,你應該慶幸自己這趟面試來得值了。為啥?下面的這九大步,面試官還不得當場呆住,這波穩(wěn)了的節(jié)奏~

·?MapJoin
如果不指定MapJoin或者不符合MapJoin的條件,那么Hive解析器會將Join操作轉(zhuǎn)換成Common Join,即:在Reduce階段完成join。容易發(fā)生數(shù)據(jù)傾斜。可以用MapJoin把小表全部加載到內(nèi)存在map端進行join,避免reducer處理。
·?行列過濾
列處理:在SELECT中,只拿需要的列,如果有,盡量使用分區(qū)過濾,少用SELECT *。
行處理:在分區(qū)剪裁中,當使用外關聯(lián)時,如果將副表的過濾條件寫在Where后面,那么就會先全表關聯(lián),之后再過濾。
·?合理設置Map數(shù)
是不是map數(shù)越多越好?
答案是否定的。如果一個任務有很多小文件(遠遠小于塊大小128m),則每個小文件也會被當做一個塊,用一個map任務來完成,而一個map任務啟動和初始化的時間遠遠大于邏輯處理的時間,就會造成很大的資源浪費。而且,同時可執(zhí)行的map數(shù)是「受限」的。此時我們就應該減少map數(shù)量。
·?合理設置Reduce數(shù)
Reduce個數(shù)并不是越多越好
(1)過多的啟動和初始化Reduce也會消耗時間和資源;
(2)另外,有多少個Reduce,就會有多少個輸出文件,如果生成了很多個小文件,那么如果這些小文件作為下一個任務的輸入,則也會出現(xiàn)小文件過多的問題;
在設置Reduce個數(shù)的時候也需要考慮這兩個「原則」:處理大數(shù)據(jù)量利用合適的Reduce數(shù);使單個Reduce任務處理數(shù)據(jù)量大小要合適;
·?嚴格模式
嚴格模式下,會有以下特點:
①對于分區(qū)表,用戶不允許掃描所有分區(qū)
②使用了order by語句的查詢,要求必須使用limit語句
③限制笛卡爾積的查詢
·?開啟map端combiner(不影響最終業(yè)務邏輯)
這個就屬于配置層面上的優(yōu)化了,需要我們手動開啟?sethive.map.aggr=true;
·?壓縮(選擇快的)
設置map端輸出中間結果壓縮。(不完全是解決數(shù)據(jù)傾斜的問題,但是減少了IO讀寫和網(wǎng)絡傳輸,能提高很多效率)
·?小文件進行合并
在Map執(zhí)行前合并小文件,減少Map數(shù):CombineHiveInputFormat具有對小文件進行合并的功能(系統(tǒng)默認的格式)。HiveInputFormat沒有對小文件合并功能。
·?其他
列式存儲,采用分區(qū)技術,開啟JVM重用...類似的技術非常多,大家選擇一些方便記憶的就OK。
11、了解過數(shù)據(jù)傾斜嗎,是如何產(chǎn)生的,你又是怎么解決的?

·?概念:
數(shù)據(jù)的分布不平衡,某些地方特別多,某些地方又特別少,導致的在處理數(shù)據(jù)的時候,有些很快就處理完了,而有些又遲遲未能處理完,導致整體任務最終遲遲無法完成,這種現(xiàn)象就是「數(shù)據(jù)傾斜」
·?如何產(chǎn)生
① ?key的分布不均勻或者說某些key太集中
② 業(yè)務數(shù)據(jù)自身的特性,例如不同數(shù)據(jù)類型關聯(lián)產(chǎn)生數(shù)據(jù)傾斜?
③ SQL語句導致的數(shù)據(jù)傾斜
·?如何解決
① 開啟map端combiner(不影響最終業(yè)務邏輯)
② 開啟數(shù)據(jù)傾斜時負載均衡
③ 控制空值分布
“將為空的key轉(zhuǎn)變?yōu)樽址与S機數(shù)或純隨機數(shù),將因空值而造成傾斜的數(shù)據(jù)分配到多個Reducer”
④ SQL語句調(diào)整
“
a ) 選用join key 分布最均勻的表作為驅(qū)動表。做好列裁剪和filter操作,以達到兩表join的時候,數(shù)據(jù)量相對變小的效果。
b ) 大小表Join:使用map join讓小的維度表(1000條以下的記錄條數(shù))先進內(nèi)存。在Map端完成Join。
c ) 大表Join大表:A表加隨機數(shù) B表擴容 后再Join
d ) count distinct大量相同特殊值:count distinct 時,將值為空的情況單獨處理,如果是計算count distinct,可以不用處理,直接過濾,在最后結果中加1。如果還有其他計算,需要進行group by,可以先將值為空的記錄單獨處理,再和其他計算結果進行union。
”
12、分區(qū)表和分桶表各自的優(yōu)點能介紹一下嗎?
·?分區(qū)表
·?介紹
1、分區(qū)使用的是表外字段,需要指定字段類型
2、分區(qū)通過關鍵字 partitioned by(partition_name string) 聲明
3、分區(qū)劃分粒度較粗
·?優(yōu)點
將數(shù)據(jù)按區(qū)域劃分開,查詢時不用掃描無關的數(shù)據(jù),加快查詢速度
·?分桶表
·??介紹
1、分桶使用的是表內(nèi)字段,已經(jīng)知道字段類型,不需要再指定。
2、分桶表通過關鍵字clustered by(column_name) into ... buckets聲明
3、分桶是更細粒度的劃分、管理數(shù)據(jù),可以對表進行先分區(qū)再分桶的劃分策略
·?優(yōu)點
? ?? ? ?用于數(shù)據(jù)取樣;能夠起到優(yōu)化加速的作用
??回答到這里已經(jīng)非常不錯,面試官可能又問了:
「小伙幾,能講解一下分桶的邏輯嗎?」
哈哈哈,有備而來,絲毫不懼?。?!
“
分桶邏輯:對分桶字段求哈希值,用哈希值與分桶的數(shù)量取余,余幾,這個數(shù)據(jù)就放在那個桶內(nèi)。
”
13、用的是動態(tài)分區(qū)嗎?動態(tài)分區(qū)的底層原理是什么?
都到了這一步,沒有撤退可言。
·?靜態(tài)分區(qū)與動態(tài)分區(qū)的主要區(qū)別在于靜態(tài)分區(qū)是手動指定,而動態(tài)分區(qū)是通過數(shù)據(jù)來進行判斷
·?詳細來說,靜態(tài)分區(qū)的列是在編譯時期,通過用戶傳遞來決定的;動態(tài)分區(qū)只有在 SQL 執(zhí)行時才能決定
·?簡單理解就是靜態(tài)分區(qū)是只給固定的值,動態(tài)分區(qū)是基于查詢參數(shù)的位置去推斷分區(qū)的名稱,從而建立分區(qū)
14、使用過Hive的視圖和索引嗎,簡單介紹一下
·?Hive視圖
視圖是一種使用查詢語句定義的「虛擬表」,是數(shù)據(jù)的一種「邏輯結構」,創(chuàng)建視圖時不會把視圖存儲到磁盤上,定義視圖的查詢語句只有在執(zhí)行視圖的語句時才會被執(zhí)行。
通過引入視圖機制,可以簡化查詢邏輯,提高了用戶效率與用戶滿意度。
「注意:」視圖是只讀的,不能向視圖中插入或是加載數(shù)據(jù)
·?Hive索引
和關系型數(shù)據(jù)庫中的索引一樣,Hive也支持在表中建立索引。適當?shù)乃饕梢詢?yōu)化Hive查詢數(shù)據(jù)的性能。但是索引需要額外的存儲空間,因此在創(chuàng)建索引時需要考慮索引的必要性。
「注意:」Hive不支持直接使用DROP TABLE語句刪除索引表。如果創(chuàng)建索引的表被刪除了,則其對應的索引和索引表也會被刪除;如果表的某個分區(qū)被刪除了,則該分區(qū)對應的分區(qū)索引也會被刪除。