Hive 系列(一)—— Hive 簡介及核心概念
一、簡介
Hive 是一個構建在 Hadoop 之上的資料倉庫,它可以將結構化的資料檔案對映成表,並提供類 SQL 查詢功能,用於查詢的 SQL 語句會被轉化為 MapReduce 作業,然後提交到 Hadoop 上執行。
特點:
- 簡單、容易上手 (提供了類似 sql 的查詢語言 hql),使得精通 sql 但是不瞭解 Java 程式設計的人也能很好地進行大資料分析;
- 靈活性高,可以自定義使用者函式 (UDF) 和儲存格式;
- 為超大的資料集設計的計算和儲存能力,叢集擴充套件容易;
- 統一的元資料管理,可與 presto/impala/sparksql 等共享資料;
- 執行延遲高,不適合做資料的實時處理,但適合做海量資料的離線處理。
二、Hive的體系架構
2.1 command-line shell & thrift/jdbc
可以用 command-line shell 和 thrift/jdbc 兩種方式來操作資料:
- command-line shell:通過 hive 命令列的的方式來操作資料;
- thrift/jdbc:通過 thrift 協議按照標準的 JDBC 的方式操作資料。
2.2 Metastore
在 Hive 中,表名、表結構、欄位名、欄位型別、表的分隔符等統一被稱為元資料。所有的元資料預設儲存在 Hive 內建的 derby 資料庫中,但由於 derby 只能有一個例項,也就是說不能有多個命令列客戶端同時訪問,所以在實際生產環境中,通常使用 MySQL 代替 derby。
Hive 進行的是統一的元資料管理,就是說你在 Hive 上建立了一張表,然後在 presto/impala/sparksql 中都是可以直接使用的,它們會從 Metastore 中獲取統一的元資料資訊,同樣的你在 presto/impala/sparksql 中建立一張表,在 Hive 中也可以直接使用。
2.3 HQL的執行流程
Hive 在執行一條 HQL 的時候,會經過以下步驟:
- 語法解析:Antlr 定義 SQL 的語法規則,完成 SQL 詞法,語法解析,將 SQL 轉化為抽象 語法樹 AST Tree;
- 語義解析:遍歷 AST Tree,抽象出查詢的基本組成單元 QueryBlock;
- 生成邏輯執行計劃:遍歷 QueryBlock,翻譯為執行操作樹 OperatorTree;
- 優化邏輯執行計劃:邏輯層優化器進行 OperatorTree 變換,合併不必要的 ReduceSinkOperator,減少 shuffle 資料量;
- 生成物理執行計劃:遍歷 OperatorTree,翻譯為 MapReduce 任務;
- 優化物理執行計劃:物理層優化器進行 MapReduce 任務的變換,生成最終的執行計劃。
關於 Hive SQL 的詳細執行流程可以參考美團技術團隊的文章:Hive SQL 的編譯過程
三、資料型別
3.1 基本資料型別
Hive 表中的列支援以下基本資料型別:
大類 | 型別 |
---|---|
Integers(整型) | TINYINT—1 位元組的有符號整數 SMALLINT—2 位元組的有符號整數 INT—4 位元組的有符號整數 BIGINT—8 位元組的有符號整數 |
Boolean(布林型) | BOOLEAN—TRUE/FALSE |
Floating point numbers(浮點型) | FLOAT— 單精度浮點型 DOUBLE—雙精度浮點型 |
Fixed point numbers(定點數) | DECIMAL—使用者自定義精度定點數,比如 DECIMAL(7,2) |
String types(字串) | STRING—指定字符集的字元序列 VARCHAR—具有最大長度限制的字元序列 CHAR—固定長度的字元序列 |
Date and time types(日期時間型別) | TIMESTAMP — 時間戳 TIMESTAMP WITH LOCAL TIME ZONE — 時間戳,納秒精度 DATE—日期型別 |
Binary types(二進位制型別) | BINARY—位元組序列 |
TIMESTAMP 和 TIMESTAMP WITH LOCAL TIME ZONE 的區別如下:
- TIMESTAMP WITH LOCAL TIME ZONE:使用者提交時間給資料庫時,會被轉換成資料庫所在的時區來儲存。查詢時則按照查詢客戶端的不同,轉換為查詢客戶端所在時區的時間。
- TIMESTAMP :提交什麼時間就儲存什麼時間,查詢時也不做任何轉換。
3.2 隱式轉換
Hive 中基本資料型別遵循以下的層次結構,按照這個層次結構,子型別到祖先型別允許隱式轉換。例如 INT 型別的資料允許隱式轉換為 BIGINT 型別。額外注意的是:按照型別層次結構允許將 STRING 型別隱式轉換為 DOUBLE 型別。
3.3 複雜型別
型別 | 描述 | 示例 |
---|---|---|
STRUCT | 類似於物件,是欄位的集合,欄位的型別可以不同,可以使用 名稱.欄位名 方式進行訪問 |
STRUCT ('xiaoming', 12 , '2018-12-12') |
MAP | 鍵值對的集合,可以使用 名稱[key] 的方式訪問對應的值 |
map('a', 1, 'b', 2) |
ARRAY | 陣列是一組具有相同型別和名稱的變數的集合,可以使用 名稱[index] 訪問對應的值 |
ARRAY('a', 'b', 'c', 'd') |
3.4 示例
如下給出一個基本資料型別和複雜資料型別的使用示例:
CREATE TABLE students(
name STRING, -- 姓名
age INT, -- 年齡
subject ARRAY<STRING>, --學科
score MAP<STRING,FLOAT>, --各個學科考試成績
address STRUCT<houseNumber:int, street:STRING, city:STRING, province:STRING> --家庭居住地址
) ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t";
四、內容格式
當資料儲存在文字檔案中,必須按照一定格式區別行和列,如使用逗號作為分隔符的 CSV 檔案 (Comma-Separated Values) 或者使用製表符作為分隔值的 TSV 檔案 (Tab-Separated Values)。但此時也存在一個缺點,就是正常的檔案內容中也可能出現逗號或者製表符。
所以 Hive 預設使用了幾個平時很少出現的字元,這些字元一般不會作為內容出現在檔案中。Hive 預設的行和列分隔符如下表所示。
分隔符 | 描述 |
---|---|
\n | 對於文字檔案來說,每行是一條記錄,所以可以使用換行符來分割記錄 |
^A (Ctrl+A) | 分割欄位 (列),在 CREATE TABLE 語句中也可以使用八進位制編碼 \001 來表示 |
^B | 用於分割 ARRAY 或者 STRUCT 中的元素,或者用於 MAP 中鍵值對之間的分割, 在 CREATE TABLE 語句中也可以使用八進位制編碼 \002 表示 |
^C | 用於 MAP 中鍵和值之間的分割,在 CREATE TABLE 語句中也可以使用八進位制編碼 \003 表示 |
使用示例如下:
CREATE TABLE page_view(viewTime INT, userid BIGINT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\001'
COLLECTION ITEMS TERMINATED BY '\002'
MAP KEYS TERMINATED BY '\003'
STORED AS SEQUENCEFILE;
五、儲存格式
5.1 支援的儲存格式
Hive 會在 HDFS 為每個資料庫上建立一個目錄,資料庫中的表是該目錄的子目錄,表中的資料會以檔案的形式儲存在對應的表目錄下。Hive 支援以下幾種檔案儲存格式:
格式 | 說明 |
---|---|
TextFile | 儲存為純文字檔案。 這是 Hive 預設的檔案儲存格式。這種儲存方式資料不做壓縮,磁碟開銷大,資料解析開銷大。 |
SequenceFile | SequenceFile 是 Hadoop API 提供的一種二進位制檔案,它將資料以<key,value>的形式序列化到檔案中。 這種二進位制檔案內部使用 Hadoop 的標準的 Writable 介面實現序列化和反序列化。它與 Hadoop API 中的 MapFile 是互相相容的。 Hive 中的 SequenceFile 繼承自 Hadoop API 的 SequenceFile,不過它的 key 為空,使用 value 存放實際的值, 這樣是為了避免 MR 在執行 map 階段進行額外的排序操作。 |
RCFile | RCFile 檔案格式是 FaceBook 開源的一種 Hive 的檔案儲存格式,首先將表分為幾個行組, 對每個行組內的資料按列儲存,每一列的資料都是分開儲存。 |
ORC Files | ORC 是在一定程度上擴充套件了 RCFile,是對 RCFile 的優化。 |
Avro Files | Avro 是一個數據序列化系統,設計用於支援大批量資料交換的應用。 它的主要特點有:支援二進位制序列化方式,可以便捷,快速地處理大量資料; 動態語言友好,Avro 提供的機制使動態語言可以方便地處理 Avro 資料。 |
Parquet | Parquet 是基於 Dremel 的資料模型和演算法實現的,面向分析型業務的列式儲存格式。 它通過按列進行高效壓縮和特殊的編碼技術,從而在降低儲存空間的同時提高了 IO 效率。 |
以上壓縮格式中 ORC 和 Parquet 的綜合性能突出,使用較為廣泛,推薦使用這兩種格式。
5.2 指定儲存格式
通常在建立表的時候使用 STORED AS
引數指定:
CREATE TABLE page_view(viewTime INT, userid BIGINT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\001'
COLLECTION ITEMS TERMINATED BY '\002'
MAP KEYS TERMINATED BY '\003'
STORED AS SEQUENCEFILE;
各個儲存檔案型別指定方式如下:
- STORED AS TEXTFILE
- STORED AS SEQUENCEFILE
- STORED AS ORC
- STORED AS PARQUET
- STORED AS AVRO
- STORED AS RCFILE
六、內部表和外部表
內部表又叫做管理表 (Managed/Internal Table),建立表時不做任何指定,預設建立的就是內部表。想要建立外部表 (External Table),則需要使用 External 進行修飾。 內部表和外部表主要區別如下:
內部表 | 外部表 | |
---|---|---|
資料儲存位置 | 內部表資料儲存的位置由 hive.metastore.warehouse.dir 引數指定,預設情況下表的資料儲存在 HDFS 的 /user/hive/warehouse/資料庫名.db/表名/ 目錄下 |
外部表資料的儲存位置建立表時由 Location 引數指定; |
匯入資料 | 在匯入資料到內部表,內部表將資料移動到自己的資料倉庫目錄下,資料的生命週期由 Hive 來進行管理 | 外部表不會將資料移動到自己的資料倉庫目錄下,只是在元資料中儲存了資料的位置 |
刪除表 | 刪除元資料(metadata)和檔案 | 只刪除元資料(metadata) |
參考資料
- Hive Getting Started
- Hive SQL 的編譯過程
- LanguageManual DDL
- LanguageManual Types
- Managed vs. External Tables
更多大資料系列文章可以參見 GitHub 開源專案: 大資料入門指南