萬字長文詳解 Hive 入門基礎
1.Hive 簡介
1.1 簡介
而 Hive 主要解決**「存儲和計算問題」**。
Hive 是由 Facebook 開源的基於 Hadoop 的數據倉庫工具,用於解決海量**「結構化日誌」**的數據統計。
簡單來說,Hive 是在 Hadoop 上**「封裝了一層 HQL 的接口」**,這樣開發人員和數據分析人員就可以使用 HQL 來進行數據的分析,而無需關注底層的 MapReduce 的編程開發。
所以 Hive 的本質是**「將 HQL 轉換成 MapReduce 程序」**。
1.2 優缺點
1.2.1 優點
-
Hive 封裝了一層接口,並提供類 SQL 的查詢功能,避免去寫 MapReduce,減少了開發人員的學習成本;
-
Hive 支持用戶自定義函數,可以根據自己的需求來實現自己的函數;
-
適合處理大數據:;
-
可擴展性強:可以自由擴展集羣的規模,不需要重啓服務而進行橫向擴展;
-
容錯性強:可以保障即使有節點出現問題,SQL 語句也可以完成執行;
1.2.2 缺點
-
Hive 不支持記錄級別的增刪改操作,但是可以通過查詢創建新表來將結果導入到文件中;(hive 2.3.2 版本支持記錄級別的插入操作)
-
Hive 延遲較高,不適用於實時分析;
-
Hive 不支持事物,因爲沒有增刪改,所以主要用來做 OLAP(聯機分析處理),而不是 OLTP(聯機事物處理);
-
Hive 自動生成的 MapReduce 作業,通常情況下不夠智能。
1.3 架構原理
放上一張很經典的 Hive 架構圖:
如上圖所示:
-
Hive 提供了 CLI(hive shell)、JDBC/ODBC(Java 訪問 hive)、WeibGUI 接口(瀏覽器訪問 hive);
-
Hive 中有一個元數據存儲(Metastore),通常是存儲在關係數據庫中如 MySQL、Derby 等。元數據包括表名、表所在數據庫、表的列名、分區及屬性、表的屬性、表的數據所在的目錄等;
-
Thrift Server 爲 Facebook 開發的一個軟件框架,可以用來進行可擴展且跨語言的服務開發,Hive 通過集成了該服務能夠讓不同編程語言調用 Hive 的接口;
-
Hadoop 使用 HDFS 進行存儲,並使用 MapReduce 進行計算;
-
Diver 中包含解釋器(Interpreter)、編譯器(Compiler)、優化器(Optimizer)和執行器(Executor):
-
「解釋器」:利用第三方工具將 HQL 查詢語句轉換成抽象語法樹 AST,並對 AST 進行語法分析,比如說表是否存在、字段是否存在、SQL 語義是否有誤;
-
「編譯器」:將 AST 編譯生成邏輯執行計劃;
-
「優化器」:多邏輯執行單元進行優化;
-
「執行器」:把邏輯執行單元轉換成可以運行的物理計劃,如 MapReduce、Spark。
所以 Hive 查詢的大致流程爲:通過用戶交互接口接收到 HQL 的指令後,經過 Driver 結合元數據進行類型檢測和語法分析,並生成一個邏輯方法,通過進行優化後生成 MapReduce,並提交到 Hadoop 中執行,並把執行的結果返回給用戶交互接口。
1.4 與 RDBMS 的比較
Hive 採用類 SQL 的查詢語句,所以很容易將 Hive 與關係型數據庫(RDBMS)進行對比。但其實 Hive 除了擁有類似 SQL 的查詢語句外,再無類似之處。我們需要明白的是:數據庫可以用做 online 應用;而 Hive 是爲數據倉庫設計的。
Hive/RDBMS
2.Hive 基本操作
2.1 Hive 常用命令
在終端輸入 hive -help 會出現:
usage: hive
-d,--define <key=value> Variable substitution to apply to Hive
commands. e.g. -d A=B or --define A=B
--database <databasename> Specify the database to use
-e <quoted-query-string> SQL from command line
-f <filename> SQL from files
-H,--help Print help information
--hiveconf <property=value> Use value for given property
--hivevar <key=value> Variable substitution to apply to Hive
commands. e.g. --hivevar A=B
-i <filename> Initialization SQL file
-S,--silent Silent mode in interactive shell
-v,--verbose Verbose mode (echo executed SQL to the
console)
常用的兩個命令是 "-e" 和 "-f":
- "-e" 表示不進入 hive cli 直接執行 SQL 語句;
hive -e "select * from teacher;"
- "-f" 表示執行 SQL 語句的腳本(方便用 crontab 進行定時調度);
hive -f /opt/module/datas/hivef.sql
2.2 本地文件導入 Hive 表中
首先需要創建一張表:
create table student(
id int,
name string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
簡單介紹下字段:
-
ROW FORMAT DELIMITED:分隔符的設置的開始語句;
-
FIELDS TERMINATED BY:設置每一行字段與字段之間的分隔符,我們這是用 '\t' 進行劃分;
除此之外,還有其他的分割符設定:
-
COLLECTION ITEMS TERMINATED BY:設置一個複雜類型(array/struct)字段的各個 item 之間的分隔符;
-
MAP KEYS TERMINATED BY:設置一個複雜類型(Map)字段的 key value 之間的分隔符;
-
LINES TERMINATED BY:設置行與行之間的分隔符;
這裏需要注意的是 ROW FORMAT DELIMITED 必須在其它分隔設置之前;LINES TERMINATED BY 必須在其它分隔設置之後,否則會報錯。
然後,我們需要準備一個文件:
# stu.txt
1 Xiao_ming
2 xiao_hong
3 xiao_hao
需要注意,每行內的字段需要用 '\t' 進行分割。
接着需要使用 load 語法加載本地文件,load 語法爲:
load data [local] inpath 'filepath' [overwrite] into table tablename [partition (partcol1=val1,partcol2=val2...)]
-
local 用來控制選擇本地文件還是 hdfs 文件;
-
overwrite 可以選擇是否覆蓋原來數據;
-
partition 可以制定分區;
hive> load data local inpath '/Users/***/Desktop/stu1.txt' into table student;
最後查看下數據:
hive> select * from student;
OK
1 Xiao_ming
2 xiao_hong
3 xiao_hao
Time taken: 1.373 seconds, Fetched: 3 row(s)
2.3 Hive 其他操作
-
quit:不提交數據退出;
-
exit:先隱性提交數據,再退出。
不過這種區別只是在舊版本中有,兩者在新版本已經沒有區別了。
在 hive cli 中可以用以下命令查看 hdfs 文件系統和本地文件系統:
dfs -ls /; # 查看 hdfs 文件系統
! ls ./; # 查看本地文件系統
用戶根目錄下有一個隱藏文件記錄着 hive 輸入的所有歷史命令:
cat ./hivehistory
注意:hive 語句不區分大小寫。
3.Hive 常見屬性配置
3.1 數據倉庫位置
Default 的數據倉庫原始位置是在 hdfs 上的:/user/hive/warehoues 路徑下。如果某張表屬於 Default 數據庫,那麼會直接在數據倉庫目錄創建一個文件夾。
我們以剛剛創建的表爲例,來查詢其所在集羣位置:
hive> desc formatted student;
OK
# col_name data_type comment
id int
name string
# Detailed Table Information
Database: default
OwnerType: USER
Owner: **
CreateTime: Fri Jul 17 08:59:14 CST 2020
LastAccessTime: UNKNOWN
Retention: 0
Location: hdfs://localhost:9000/user/hive/warehouse/student
Table Type: MANAGED_TABLE
Table Parameters:
bucketing_version 2
numFiles 1
numRows 0
rawDataSize 0
totalSize 34
transient_lastDdlTime 1594948899
# Storage Information
SerDe Library: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
InputFormat: org.apache.hadoop.mapred.TextInputFormat
OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
Compressed: No
Num Buckets: -1
Bucket Columns: []
Sort Columns: []
Storage Desc Params:
field.delim \t
serialization.format \t
Time taken: 0.099 seconds, Fetched: 32 row(s)
可以看到,Table Information 裏面有一個 Location,表示當前表所在的位置,因爲 student 是 Default 數據倉庫的,所以會在 '/user/hive/warehouse/' 路徑下。
如果我們想要修改 Default 數據倉庫的原始位置,需要在 hive-site.xml(可以來自 hive-default.xml.template)文件下加入如下配置信息,並修改其 value:
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property>
同時也需要給修改的路徑配置相應的權限:
hdfs dfs -chmod g+w /user/hive/warehouse
3.2 查詢信息顯示配置
我們可以在 hive-site.xml 中配置如下信息,便可以實現顯示當前數據庫以及查詢表的頭信息:
<property>
<name>hive.cli.print.header</name>
<value>true</value>
</property>
<property>
<name>hive.cli.print.current.db</name>
<value>true</value>
</property>
當然我們也可以通過 set 命令來設置:
set hive.cli.print.header=true; # 顯示錶頭
set hive.cli.print.current.db=true; # 顯示當前數據庫
看下前後的對比:
# 前
hive> select * from studenT;
OK
1 Xiao_ming
2 xiao_hong
3 xiao_hao
Time taken: 0.231 seconds, Fetched: 3 row(s)
# 後
hive (default)> select * from student;
OK
student.id student.name
1 Xiao_ming
2 xiao_hong
3 xiao_hao
Time taken: 0.202 seconds, Fetched: 3 row(s)
3.3 參數配置方式
可以用 set 查看當前所有參數配置信息:
hive> set
但是一般不這麼玩,會顯示很多信息。
通常配置文件有三種方式:
上述三種設定方式的優先級依次遞增。即配置文件 < 命令行參數 < 參數聲明。注意某些系統級的參數,例如 log4j 相關的設定,必須用前兩種方式設定,因爲那些參數的讀取在會話建立以前已經完成了。
4.Hive 數據類型
4.1 基本數據類型
Hive 數據類型/Java 數據類型/長度
Hive 的 String 類型相當於數據庫的 varchar 類型,該類型是一個可變的字符串,不過它不能聲明其中最多能存儲多少個字符,理論上它可以存儲 2GB 的字符數。
4.2 集合數據類型
數據類型/描述/語法示例
Hive 有三種複雜數據類型 ARRAY、MAP、STRUCT。ARRAY 和 MAP 與 Java 中的 Array 和 Map 類似,而 STRUCT 與 C 語言中的 Struct 類似,它封裝了一個命名字段集合,複雜數據類型允許任意層次的嵌套。
案例實操:
- 假設某表有如下一行,我們用 JSON 格式來表示其數據結構。在 Hive 下訪問的格式爲:
{
"name": "songsong",
"friends": ["bingbing" , "lili"] , //列表 Array,
"children": { //鍵值 Map,
"xiao song": 18 ,
"xiaoxiao song": 19
},
"address": { //結構 Struct,
"street": "hui long guan" ,
"city": "beijing"
}
}
- 基於上述數據結構,我們在 Hive 裏創建對應的表,並導入數據。創建本地測試文件 text.txt:
songsong,bingbing_lili,xiao song:18_xiaoxiao song:19,hui long guan_beijing yangyang,caicai_susu,xiao yang:18_xiaoxiao yang:19,chao yang_beijing
注意:MAP,STRUCT 和 ARRAY 裏的元素間關係都可以用同一個字符表示,這裏用 “_”。
- Hive 上創建測試表 test:
create table test(
name string,
friends array<string>,
children map<string, int>,
address struct<street:string, city:string>
)
row format delimited
fields terminated by ','
collection items terminated by '_'
map keys terminated by ':'
lines terminated by '\n';
字段解釋:
-
row format delimited fields terminated by ',':列分隔符;
-
collection items terminated by '_':MAP STRUCT 和 ARRAY 的分隔符 (數據分割符號);
-
map keys terminated by ':':MAP 中的 key 與 value 的分隔符;
-
lines terminated by '\n':行分隔符。
- 導入文本數據到測試表中:
hive (default)> load data local inpath '/Users/chenze/Desktop/test.txt' into table test;
- 訪問三種集合列裏的數據:
先查看下數據:
hive (default)> select * from test;
OK
test.name test.friends test.children test.address
songsong ["bingbing","lili"] {"xiao song":18,"xiaoxiao song":19} {"street":"hui long guan","city":"beijing yangyang"}
Time taken: 0.113 seconds, Fetched: 1 row(s)
查看 ARRAY,MAP,STRUCT 的訪問方式:
hive (default)> select friends[1],children['xiao song'],address.city from test where ;
OK
_c0 _c1 city
lili 18 beijing yangyang
Time taken: 0.527 seconds, Fetched: 1 row(s)
4.3 數據類型轉化
Hive 的原子數據類型是可以進行隱式轉換的,類似於 Java 的類型轉換,例如某表達式使用 INT 類型,TINYINT 會自動轉換爲 INT 類型,但是 Hive 不會進行反向轉化,例如,某表達式使用 TINYINT 類型,INT 不會自動轉換爲 TINYINT 類型,它會返回錯誤,除非使用 CAST 操作。
-
隱式類型轉換規則如下
-
任何整數類型都可以隱式地轉換爲一個範圍更廣的類型,如 TINYINT 可以轉換 成 INT,INT 可以轉換成 BIGINT;
-
所有整數類型、FLOAT 和 STRING 類型都可以隱式地轉換成 DOUBLE;
-
TINYINT、SMALLINT、INT 都可以轉換爲 FLOAT;
-
BOOLEAN 類型不可以轉換爲任何其它的類型。
-
可以使用 CAST 操作顯示進行數據類型轉換
例如 CAST('1' AS INT) 將把字符串 '1' 轉換成整數 1;如果強制類型轉換失敗,如執行 CAST('X' AS INT),表達式返回空值 NULL。
- 數據組織 =======
1、Hive 的存儲結構包括**「數據庫、表、視圖、分區和表數據」**等。數據庫,表,分區等等都對 應 HDFS 上的一個目錄。表數據對應 HDFS 對應目錄下的文件。
2、Hive 中所有的數據都存儲在 HDFS 中,沒有專門的數據存儲格式,因爲 「Hive 是讀模式」 (Schema On Read),可支持 TextFile,SequenceFile,RCFile 或者自定義格式等。
-
「TextFile」:默認格式,存儲方式爲行存儲。數據不做壓縮,磁盤開銷大,數據解析開銷大;
-
「SequenceFile」:Hadoop API 提供的一種二進制文件支持,其具有使用方便、可分割、可壓縮的特點。SequenceFile 支持三種壓縮選擇:NONE, RECORD, BLOCK。Record 壓縮率低,一般建議使用 BLOCK 壓縮;
-
「RCFile」:一種行列存儲相結合的存儲方式;
-
「ORCFile」:數據按照行分塊,每個塊按照列存儲,其中每個塊都存儲有一個索引。Hive 給出的新格式,屬於 RCFILE 的升級版,性能有大幅度提升,而且數據可以壓縮存儲,壓縮快,且可以快速列存取;
-
「Parquet」:一種行式存儲,同時具有很好的壓縮性能;同時可以減少大量的表掃描和反序列化的時間。
3、 只需要在創建表的時候告訴 Hive 數據中的**「列分隔符和行分隔符」**,Hive 就可以解析數據
-
Hive 的默認列分隔符:控制符 「Ctrl + A,\x01 Hive」 的;
-
Hive 的默認行分隔符:換行符 「\n」。
4、Hive 中包含以下數據模型:
-
「database」:在 HDFS 中表現爲 ${hive.metastore.warehouse.dir} 目錄下一個文件夾;
-
「table」:在 HDFS 中表現所屬 database 目錄下一個文件夾;
-
「external table」:與 table 類似,不過其數據存放位置可以指定任意 HDFS 目錄路徑;
-
「partition」:在 HDFS 中表現爲 table 目錄下的子目錄;
-
「bucket」:在 HDFS 中表現爲同一個表目錄或者分區目錄下根據某個字段的值進行 hash 散列之後的多個文件;
-
「view」:與傳統數據庫類似,只讀,基於基本表創建
5、Hive 的元數據存儲在 RDBMS 中,除元數據外的其它所有數據都基於 HDFS 存儲。默認情 況下,Hive 元數據保存在內嵌的 Derby 數據庫中,只能允許一個會話連接,只適合簡單的 測試。實際生產環境中不適用,爲了支持多用戶會話,則需要一個獨立的元數據庫,使用 MySQL 作爲元數據庫,Hive 內部對 MySQL 提供了很好的支持。
6、Hive 中的表分爲內部表、外部表、分區表和 Bucket 表
-
「內部表和外部表的區別:」
-
創建內部表時,會將數據移動到數據倉庫指向的路徑;創建外部表時,僅記錄數據所在路徑,不對數據的位置做出改變;
-
刪除內部表時,刪除表元數據和數據 ; 刪除外部表時,刪除元數據,不刪除數據。所以外部表相對來說更加安全些,數據組織也更加靈活,方便共享源數據;
-
內部表數據由 Hive 自身管理,外部表數據由 HDFS 管理;
-
未被 external 修飾的是內部表,被 external 修飾的爲外部表;
-
對內部表的修改會直接同步到元數據,而對外部表的表結構和分區進行修改,則需要修改'MSCK REPAIR TABLE [table_name]'。
-
「內部表和外部表的使用選擇:」
-
大多數情況,他們的區別不明顯,如果數據的所有處理都在 Hive 中進行,那麼傾向於選擇內部表;但是如果 Hive 和其他工具要針對相同的數據集進行處理,外部表更合適;
-
使用外部表訪問存儲在 HDFS 上的初始數據,然後通過 Hive 轉換數據並存到內部表中;
-
使用外部表的場景是針對一個數據集有多個不同的 Schema;
-
通過外部表和內部表的區別和使用選擇的對比可以看出來,hive 其實僅僅只是對存儲在 HDFS 上的數據提供了一種新的抽象,而不是管理存儲在 HDFS 上的數據。所以不管創建內部表還是外部表,都可以對 hive 表的數據存儲目錄中的數據進行增刪操作。
使用外部表的場景是針對一個數據集有多個不同的 Schema
通過外部表和內部表的區別和使用選擇的對比可以看出來,hive 其實僅僅只是對存儲在 HDFS 上的數據提供了一種新的抽象。而不是管理存儲在 HDFS 上的數據。所以不管創建內部 表還是外部表,都可以對 hive 表的數據存儲目錄中的數據進行增刪操作。
-
「分區表和分桶表的區別:」
-
Hive 數據表可以根據某些字段進行分區操作,細化數據管理,可以讓部分查詢更快。同時表和分區也可以進一步被劃分爲 Buckets,分桶表的原理和 MapReduce 編程中的 HashPartitioner 的原理類似;
-
分區和分桶都是細化數據管理,但是分區表是手動添加區分,由於 Hive 是讀模式,所以對添加進分區的數據不做模式校驗,分桶表中的數據是按照某些分桶字段進行 hash 散列形成的多個文件,所以數據的準確性也高很多。
6.Reference
-
尚硅谷 Hive 教程 (新版 hive 框架詳解)
-
Hive 學習之路 (一)Hive 初識
-
Hive 內部表與外部表的區別
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/2zyXgAvpB14qi-8WAabcIg