HiveQL是Hive查詢語言。和普遍使用的所有SQL方言一樣,它不完全遵守任一種ANSISQL標準的修訂版。HiveQL可能和MySQL的方言最接近,但是兩者還是存在顯著性差異的。Hive不支持行級插入操作、更新操作和刪除操作。Hive也不支持事務。當然了,大部分的HiveQL還是很常見的。本篇首先介紹Hive中的數據庫概念以及操作細節。
1 Hive中的數據庫
1.1 創建數據庫
hive中數據庫的概念本質上僅僅是表的一個目錄或者命名空間。然而,對於具有很多組和用戶的大集羣來說,這是非常有用的,因爲這樣可以避免表命名衝突。通常會使用數據庫來將生產表組織成邏輯組。
如果用戶沒有顯式指定數據庫,那麼將會使用默認的數據庫default
通過下面語句創建一個數據庫:
hive> CREATE DATABASE IF NOT EXISTS financials;
hive會爲每個數據庫創建一個目錄。數據庫中的表將會以這個數據庫目錄的子目錄形式存儲。但有一個例外就是default數據庫中的表,因爲這個數據庫本身沒有自己的目錄。數據庫所在的目錄位於屬性hive.metastore.warehouse.dir所指定的頂層目錄之後,假設配置項的值是/hive/warehouse,那麼當我們創建數據庫financials時,hive將會對應地創建一個目錄/hive/warehouse/financials.db。這裏請注意,數據庫的文件目錄名是以.db結尾的。
上圖除了紅框處的其他目錄都是默認數據庫default裏的表目錄
我們可以通過如下的命令來修改這個默認的位置:
hive> CREATE DATABASE IF NOT EXISTS financials
> LOCATION '/user';
還可以爲這個數據庫增加一個描述信息,這樣通過DESCRIBE DATABASE 命令就可以查看到該信息:
hive> CREATE DATABASE financials
> COMMENT 'Holds all financial tables';
從上圖結果中可以看到DESCRIBE DATABASE語句也會顯示出這個數據庫所在的文件目錄位置路徑
1.2 設置當前的工作數據庫
USE命令用於將某個數據庫設置爲用戶當前的工作數據庫,和在文件系統中切換工作目錄是一個概念:
hive> USE financials;
然後,使用像SHOW TABLES這樣的命令就會顯示當前這個數據庫下所有的表。不幸的是,並沒有一個命令可以讓用戶查看當前所在的是哪個數據庫。幸運的是,在hive中是可以重複使用USE命令的,這是因爲在hive中並沒有嵌套數據庫的概念。
可以通過設置一個屬性值在提示符裏顯示當前所在的數據庫:
hive> set hive.cli.print.current.db=true;
1.2 刪除數據庫
最後,用戶可以刪除數據庫,執行後其在/hive/warehouse/下對應的目錄financials.db也同時被刪除:
hive> DROP DATABASE IF EXISTS financials;
默認情況下,hive是不允許用戶刪除一個包含有表的數據庫的。用戶要麼先刪除數據庫中的表,然後再刪除數據庫;要麼在刪除命令的最後加上關鍵字CASCADE,這樣可以使hive自行先刪除數據庫中的表:
hive> DROP DATABASE IF EXISTS financials CASCADE;
2 創建表
2.1 CREATE TABLE
CREATE TABLE語句遵從SQL語法慣例,但是hive的這個語句中具有顯著的功能擴展,使其可以具有更廣泛的靈活性。例如,可以定義表的數據文件存儲在什麼位置、使用什麼樣的存儲格式等等。
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name -- (Note: TEMPORARY available in Hive 0.14.0 and later)
[(col_name data_type [COMMENT col_comment], ... [constraint_specification])]
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
[CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
[SKEWED BY (col_name, col_name, ...) -- (Note: Available in Hive 0.10.0 and later)]
ON ((col_value, col_value, ...), (col_value, col_value, ...), ...)
[STORED AS DIRECTORIES]
[
[ROW FORMAT row_format]
[STORED AS file_format]
| STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)] -- (Note: Available in Hive 0.6.0 and later)
]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value, ...)] -- (Note: Available in Hive 0.6.0 and later)
[AS select_statement]; -- (Note: Available in Hive 0.5.0 and later; not supported for external tables)
其中,ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’通過指定的分隔符(這裏是’\t’)將行分解成列。如果某行的字段個數比預期的要少,那麼缺少的字段將返回null;如果某行的字段個數比預期的要多,那麼多出的字段將會被省略掉。
根據上述經建表命令格式,創建一個employees表:
CREATE TABLE IF NOT EXISTS mydb.employees (
name STRING COMMENT 'Employee name',
salary FLOAT COMMENT 'Employee salary',
subordinates ARRAY<STRING> COMMENT 'Names of subordinates',
deductions MAP<STRING, FLOAT> COMMENT 'Keys are deductions names, values are percentages',
address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT> COMMENT 'Home address' )
COMMENT 'Description of the table'
LOCATION '/hive/warehouse/mydb.db/employees'
TBLPROPERTIES ('creator'='by', 'created_at'='2019-05-03 17:26');
首先可以看到,如果我們當前所處的數據庫並非是目標數據庫,那麼是可以在表名前增加一個數據庫名來進行指定的,也就是mydb。
我們可以在字段類型後爲每個字段增加一個註釋。和數據庫一樣,我們也可以爲表本身添加一個註釋,還可以自定義一個或多個表屬性。大多數情況下,TBLPROPERTIES的主要作用是按鍵-值對的格式爲表增加額外的文檔說明。
最後,從例子可看出可以根據情況爲表中的數據指定一個存儲路徑。例子中是使用默認的路徑/hive/warehouse/mydb.db/employees。其中/hive/warehouse是默認的“數據倉庫”路徑地址,mydb.db是數據庫目錄,employees是表目錄。
默認情況下,hive總是將創建的表的目錄放置在這個表所屬的數據庫目錄下。不過,default數據庫是個例外,其在/hive/warehouse下並沒有對應一個數據庫目錄。因此default數據庫中的表目錄會直接位於/hive/warehouse目錄下(除非用戶明確指定其他路徑)
2.2 複製表模式
還可以拷貝一張以及存在的表的模式(而無需拷貝數據):
CREATE TABLE IF NOT EXISTS mydb.employees2 LIKE mydb.employees;
2.3 列舉所有表
SHOW TABLES命令可以列舉出所有的表,如果不增加其他參數,那麼只會顯示當前工作數據庫下的表。但即使不在我們想要的數據庫下,還是可以列舉指定數據庫下的表的:
SHOW TABLE IN mydb;
2.4 查看錶的詳細信息
接下來可以使用DESCRIBE FORMATTED mydb.employees命令來查看這個表的詳細表結構信息(如果當前所處的工作數據庫就是mydb的話,可以不加mydb.這個前綴)。
hive> DESCRIBE FORMATTED mydb.employees;
OK
# col_name data_type comment
name string Employee name
salary float Employee salary
subordinates array<string> Names of subordinates
deductions map<string,float> Keys are deductions names, values are percentages
address struct<street:string,city:string,state:string,zip:int> Home address
# Detailed Table Information
Database: mydb
Owner: root
CreateTime: Fri May 03 19:25:26 CST 2019
LastAccessTime: UNKNOWN
Protect Mode: None
Retention: 0
Location: hdfs://192.168.230.10:9000/hive/warehouse/mydb.db/employees
Table Type: MANAGED_TABLE
Table Parameters:
comment Description of the table
created_at 2019-05-03 17:26
creator by
transient_lastDdlTime 1556882726
# 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:
serialization.format 1
Time taken: 0.269 seconds, Fetched: 33 row(s)
注意以Location:開頭的那行描述信息。這個是hive在hdfs中的存儲表中數據的完整的URL目錄路徑。
2.5 管理表
我們目前所創建的表都是所謂的管理表MANAGED_TABLE,有時也被稱爲內部表。因爲這種表,hive會(或多或少地)控制着數據的生命週期。正如我們所看見的,hive默認情況下會將這些表的數據存儲在由配置項hive.metastore.warehouse.dir(例如/hive/warehouse)所定義的目錄的子目錄下。當我們刪除一個管理表時,hive也會刪除這個表中的數據。
但是,管理表不方便和其他工作共享數據。例如,假設我們有一份由Pig或者其他工具創建並且主要由這一工具使用的數據,同時我們還想使用hive在這份數據上執行一些查詢,可是並沒有給予hive對數據的所有權,我們可以創建一個外部表指向這份數據,而並不需要對其具有所有權。
2.6 外部表
假設數據文件已經位於hdfs下的/data/stocks目錄下,下面的語句將創建一個外部表,其可以讀取所有位於/data/stocks目錄下的以逗號分隔的數據:
CREATE EXTERNAL TABLE IF NOT EXISTS stocks (
exchange STRING,
symbol STRING,
ymd STRING,
price_open FLOAT,
price_high FLOAT,
price_low FLOAT,
price_close FLOAT,
volume INT,
price_adj_close FLOAT)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION '/data/stocks';
關鍵字EXTERNAL告訴hive這個表是外部的,而後面的LOCATION字句則告訴hive數據位於哪個路徑下。因爲表是外部的,所以hive並非認爲其完全擁有這份數據。因此,刪除該表並不會刪除這份數據,但是描述表的元數據信息會被刪除掉。
我們可以在DESCRIBE FORMATTED tablename語句的輸出中查看到表是否是管理表或外部表。對於管理表,我們可看到Table Type: MANAGED_TABLE,對於外部表,則是Table Type: EXTERNAL_TABLE
我們還可以對一張存在的表進行表結構複製(而不會複製數據):
CREATE EXTERNAL TABLE IF NOT EXISTS mydb.employee3
LIKE mydb.employees
LOCATION '/path/to/data';
這裏,如果上述語句中省略掉EXTERNAL關鍵字而且源表是外部表的話,那麼生成的新表也將是外部表。如果省略掉EXTERNAL而且源表是管理表的話,那麼生成的新表也將是管理表。但是,如果語句中含有EXTERNAL關鍵字而源表是管理表的話,那麼生成的新表將是外部表。
3 刪除表
hive支持和SQL中DROP TABLE命令類似的操作:
DROP TABLE IF EXISTS taable_name
對於管理表,表的元數據信息和表內的數據都會被刪除。而對於外部表,表的元數據信息會被刪除,但是表中的數據不會被刪除。
事實上,如果用戶開啓了Hadoop回收站功能(這個功能默認是關閉的),那麼數據將會被轉移到用戶在分佈式文件系統中的用戶根目錄下的.Trash目錄下,也就是HDFS中的/user/$USER/.Trash目錄。如果想開啓這個功能,只需要在core-site.xml中將配置屬性fs.trash.interval的值設置爲一個合理的正整數即可。這個值是“回收站檢查點”的時間間隔,單位是分鐘。因此如果設置值爲1440,那麼就表示24小時。如果用戶不小心刪除了一張存儲着重要數據的管理表的話,那麼可以先重建表,然後重建所需要的分區,再從.Trash目錄中將誤刪的文件移動到正確的文件目錄下來重新存儲數據。
參考:《Hive編程指南》