1. 程式人生 > >Hive 系列(一)—— Hive 簡介及核心概念

Hive 系列(一)—— Hive 簡介及核心概念

一、簡介

Hive 是一個構建在 Hadoop 之上的資料倉庫,它可以將結構化的資料檔案對映成表,並提供類 SQL 查詢功能,用於查詢的 SQL 語句會被轉化為 MapReduce 作業,然後提交到 Hadoop 上執行。

特點:

  1. 簡單、容易上手 (提供了類似 sql 的查詢語言 hql),使得精通 sql 但是不瞭解 Java 程式設計的人也能很好地進行大資料分析;
  2. 靈活性高,可以自定義使用者函式 (UDF) 和儲存格式;
  3. 為超大的資料集設計的計算和儲存能力,叢集擴充套件容易;
  4. 統一的元資料管理,可與 presto/impala/sparksql 等共享資料;
  5. 執行延遲高,不適合做資料的實時處理,但適合做海量資料的離線處理。

二、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 的時候,會經過以下步驟:

  1. 語法解析:Antlr 定義 SQL 的語法規則,完成 SQL 詞法,語法解析,將 SQL 轉化為抽象 語法樹 AST Tree;
  2. 語義解析:遍歷 AST Tree,抽象出查詢的基本組成單元 QueryBlock;
  3. 生成邏輯執行計劃:遍歷 QueryBlock,翻譯為執行操作樹 OperatorTree;
  4. 優化邏輯執行計劃:邏輯層優化器進行 OperatorTree 變換,合併不必要的 ReduceSinkOperator,減少 shuffle 資料量;
  5. 生成物理執行計劃:遍歷 OperatorTree,翻譯為 MapReduce 任務;
  6. 優化物理執行計劃:物理層優化器進行 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)

參考資料

  1. Hive Getting Started
  2. Hive SQL 的編譯過程
  3. LanguageManual DDL
  4. LanguageManual Types
  5. Managed vs. External Tables

更多大資料系列文章可以參見 GitHub 開源專案: 大資料入門指南