Hive官網
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
複製程式碼
驗證:瀏覽器訪問 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.資料儲存
- 基於HDFS的
預設儲存在
/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 format delimited fields terminated by '列分隔符'
複製程式碼
-
分割槽表
create table partition_table
(
sid int,
sname string
)
partitioned by (gender string)
row format delimited fields terminated by ',';
複製程式碼
-
外部表
create external table partition_table
(
sid int,
sname string
)
row format delimited 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'