Hive 入門
Hive 的底層執行引擎有 :MapReduce,Tez,Spark - Hive on MapReduce - Hive on Tez - Hive on spark
壓縮:GZIP,LZO,Snappy,Bzip2... 儲存:Textfile,SequenceFile,RcFile,ORC,Parquet UDF:自定義函式

為什麼要使用Hive: 簡單,容易上手(提供了類SQL的查詢語言HQL) 為超大資料集設計的計算/儲存擴充套件能力(MR計算,HDFS儲存) 統一的元資料管理(可與Pretso/Impala/SparkSQL資料共享)
Hive 的體系結構
1.Hive的元資料

2.HQL 的執行過程
- 直譯器、編譯器、優化器完成HQL查詢語句從詞法分析、語法分析、編譯、優化以及查詢計劃(PLAN)的生產,生產的查詢計劃儲存在 HDFS中,並在隨後有MapReduce呼叫執行

3.體系結構


4.Hive 生產環境部署架構

Hive 安裝

1.嵌入入模式(元資料儲存在自己維護的dirbe資料庫)
解壓好資料夾後直接進入bin目錄執行hive指令碼 ${HIVE_HOME}/bin/hive 複製程式碼
2.本地模式或者遠端模式(元資料儲存在本地或者遠端的mysql庫)
修改hive-site.xml
<!-- jdbc 引數 --> <property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://localhost:3306/hive</value> </property> <property> <name>javax.jdo.option.ConnectionDriverName</name> <value>com.mysql.jdbc.Driver</value> </property> <property> <name>javax.jdo.option.ConnectionUserName</name> <value>root</value> </property> <property> <name>javax.jdo.option.ConnectionPassword</name> <value>root</value> </property> 複製程式碼
Hive 管理
1.cli模式
# 進入cli ${HIVE_HOME}/bin/hive --service cli # 1. Hive -S進入靜默模式,不會列印MapReduce作業除錯資訊 # 2. 一般情況下,hive執行SQL都會轉換成MapReduce作業進行執行,但是如果是使用select * 則不會轉換成mr任務 ${HIVE_HOME}/bin/hive -S # 不進入互動模式 ${HIVE_HOME}/bin/hive -e {sql語句} 複製程式碼
2.web管理介面模式(只能做查詢)
-
進入hive的原始碼目錄的hwi目錄
${HIVE_SRC_HOME}/hwi
-
將其打包編譯
mvn package(需要安裝mvn環境)
-
將打好的包放入
${HIVE_HOME}/lib/
目錄下 -
修改 hive_site.xml
<!-- web介面監聽的主機地址 --> <property> <name>hive.hwi.listen.host</name> <value>0.0.0.0</value> <description>This is the host address the Hive Web Interface will listen on</description> </property> <!-- web介面監聽的埠 --> <property> <name>hive.hwi.listen.port</name> <value>9999</value> <description>This is the port the Hive Web Interface will listen on</description> </property> <!-- war包的位置 --> <property> <name>hive.hwi.war.file</name> <value>${HIVE_HOME}/lib/hive-hwi-<version>.war</value> <description>This is the WAR file with the jsp content for Hive Web Interface</description> </property> 複製程式碼
6.拷貝jdk目錄下的tools.jar 到hive的lib下
cp ${JAVA_HOME}/lib/tools.jar ${HIVE_HOME}/lib 複製程式碼
- 啟動web服務
${HIVE_HOME}/bin/hive --service hwi 複製程式碼
驗證:瀏覽器訪問 ofollow,noindex">http://localhost:9999/hwi/
3.遠端連線
${HIVE_HOME}/bin/hive --service hiveserver 複製程式碼
資料型別
1.基本資料型別

hive新版本中,新增了兩種字串型別 varchar和char varchar(20) 最大長度是20 ,可伸縮 char(20) 固定長度20 複製程式碼
2.複雜資料型別

create table student1 ( sid int , sname string, score array<float> ) create table studetnt2 ( sid int , sname string, score map<string,float> ) create table student3 ( sid int , info struct<name:string,age:int,sex:string> ) 複製程式碼
3.時間型別

timestamp 與時區無關,是自從有了unix以來的偏移量 date 描述的是特定的日期 YYYY-MM-DD 複製程式碼
資料模型
1.資料儲存
/user/hive/warehouse/
sid | sname |
---|---|
1 | Tom |
2 | Mary |
這張表在檔案中預設儲存為檔案,使用垂直製表符分割
1 Tom 2 Mary 複製程式碼
- 儲存結構主要包括:資料庫 檔案 表 檢視
- 可以直接載入文字檔案(.txt等)進行資料新增
- 建立表時,可以指定Hive資料的列分隔符和行分隔符
- 表
· Table 內部表 · Partition 分割槽表 · External 外部表 · Bucket Table 桶表 複製程式碼
2.詳解表
-
Table 內部表

create table student1 ( sid int , sname string ) location '${目錄}' row formatdelimited fields terminated by '列分隔符' 複製程式碼
-
分割槽表

create table partition_table ( sid int, sname string ) partitioned by (gender string) row formatdelimited fields terminated by ','; 複製程式碼
-
外部表


create external table partition_table ( sid int, sname string ) row formatdelimited fields terminated by ',' location '/input'; -- input 目錄中有相關資料 複製程式碼
-
桶表


create external table partition_table ( sid int, sname string ) clustered by({hash的欄位}) into {桶的數量} buckets -- input 目錄中有相關資料 複製程式碼
3.檢視


Hive 的資料匯入
1.使用load語句匯入
LOAD DATE [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1,partcol2=val2)] -- [LOCAL] 代表從本地檔案系統匯入,否則從HDFS中匯入 -- [OVERWRITE] 代表覆蓋原有的資料 -- [PARTITION] 代表分割槽 -- 如果filepah是一個檔案則匯入一個檔案的資料,如果是一個目錄,則匯入該目錄下所有的檔案 複製程式碼
2.Sqoop匯入
安裝步驟
- 下載並解壓
- 設定兩個環境變數
# hadoop目錄 export HADOOP_COMMON_HOME='/Users/gaowenfeng/software/hadoop-2.6.0-cdh5.7.0/' # MP目錄 export HADOOP_MAPRED_HOME='/Users/gaowenfeng/software/hadoop-2.6.0-cdh5.7.0/' # HIVE 目錄 export HIVE_CONF_HOME='/Users/gaowenfeng/software/hive-1.2.2/' 複製程式碼
3.使用Sqoop匯入Mysql資料到HDFS中
sqoop import --connect {jdbc_url} --username {username} --password {password} --table {table} --columns {col1,col2...} -m {mp程序數} --target-dir {path} 複製程式碼
4.使用Sqoop匯入Mysql資料Hive中
# 如果不指定表名,會在hive找那個建立一張表,表名與源表名一樣 sqoop import --hive-import --connect {jdbc_url} --username {username} --password {password} --table {table} --columns '{col1,col2...}' -m {mp程序數} --columns '{col1,col2...}' --table {target_table} --where '{where條件}' 複製程式碼
5.使用Sqoop匯入Mysql資料到Hive中並使用查詢
# 如果不指定表名,會在hive找那個建立一張表,表名與源表名一樣 sqoop import --hive-import --connect {jdbc_url} --username {username} --password {password} --table {table} --columns '{col1,col2...}' -m {mp程序數} --columns '{col1,col2...}' --table {target_table} --query 'sql語句' # sql語句必須有 and $CONDITIONS 複製程式碼
Hive 調優
-- 動態分割槽,根據插入的記錄自動分割槽 SET hive.exec.dynamic.partition=true; SET hive.exec.dynamic.partition.mode=nonstrict; -- 並行執行,子查詢可以並行執行 SET hive.exec.parallel=true; -- 計算結束以後將小檔案合併 SET hive.merge.mapredfiles=true; -- 如果某個維表小於100000000B(100M),就做MAP關聯,不用到reduce階段 SET hive.mapjoin.smalltable.filesize=100000000; -- 超時時間 SET mapred.task.timeout=1800000; -- 新增自定義jar包 ADD jar viewfs://hadoop-meituan/user/hadoop-hotel/user_upload/gaowenfeng02_hive-udf-zhaoxiang.jar; -- 建立UDF CREATE TEMPORARY FUNCTION get_tag_list as 'com.meituan.hive.udf.common.ResolveTagUdf'; -- map jvm記憶體設定3G -- SET mapred.map.child.java.opts="-Xmx3072m"; -- map task 的記憶體 約等於4G -- SET mapreduce.map.memory.mb=4000; -- reduce jvm記憶體設定3G -- SET mapred.reduce.child.java.opts="-Xmx3072m"; -- reduce task 的記憶體 約等於4G -- SET mapreduce.reduce.memory.mb=4000; 複製程式碼
Hive教程:www.yiibai.com/hive/
ETL的優化
hive.exec.reducers.bytes.per.reducer 這個引數控制一個job會有多少個reducer來處理,依據的是輸入檔案的總大小。預設1GB。(即每個reduce任務處理的資料量。)
hive.exec.reducers.max 這個引數控制最大的reducer的數量, 如果 input / bytes per reduce > max 則會啟動這個引數所指定的reduce個數。 這個並不會影響mapre.reduce.tasks引數的設定。預設的max是999。
mapred.reduce.tasks 這個引數如果指定了,hive就不會用它的estimation函式來自動計算reduce的個數,而是用這個引數來啟動reducer。預設是-1.
reduce的個數設定其實對執行效率有很大的影響: 1、如果reduce太少: 如果資料量很大,會導致這個reduce異常的慢,從而導致這個任務不能結束,也有可能會OOM 2、如果reduce太多: 產生的小檔案太多,合併起來代價太高,namenode的記憶體佔用也會增大。
如果我們不指定mapred.reduce.tasks, hive會自動計算需要多少個reducer。 計算的公式: reduce個數 = InputFileSize / bytes per reducer
mapreduce.map.memory.mb 每個Map Task需要的記憶體量 mapreduce.reduce.memory.mb 每個Reduce Task需要的記憶體量
檢視任務執行的日誌: XT平臺生產運維欄目中,排程管理下的執行日誌 測試引數:
- -delta 1 -v
測試的表名:ba_hotel_test.topic_log_mt_order_trade_entrance 線上的表名:ba_hotel.topic_log_mt_order_trade_entrance 測試流量:頁面流量,模組流量(某個頁面之前前的頁面流量一定是大於該頁面的流量)
任務流程—測試及上線: 測試完再上線,測試包括線下測試和線上測試 提交稽核,稽核通過後就自動上線了 在XT平臺中,該任務下點執行計劃,再進行線上測試
map、reduce java程式碼講解 ba_hotel.topic_log_mt_order_trade_entrance.mpt_track ba_hotel.topic_log_mt_order_trade_entrance.patch_track ba_hotel.topic_log_mt_order_trade_entrance.mge_track
ba_travel.topic_log_tag_moudle fact_log_tag_pv
優化排查: 1.最後一個map少,時間長 2.reduce一直在99%,發生了資料傾斜 3.job交接時間長,說明碎片多
優化: 1.ETL語句執行問題:問Hadoop小客服 2.子查詢,精簡資料 3.子查詢之間的關聯,是否資料傾斜 4.引數調高
測試程式碼: 線上庫: select count(uuid), count(DISTINCT uuid) from ba_hotel.topic_log_mt_order_trade_entrance where datekey='20180422' and partition_entrance_type= 'mpt' limit 10 測試庫: select count(uuid), count(DISTINCT uuid) from ba_hotel_test.topic_log_mt_order_trade_entrance where datekey='20180422' and partition_entrance_type= 'mpt'