HiveQL(一):數據庫及創建、刪除表(管理表、外部表)

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編程指南》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章