Hive編程指南讀書筆記(轉載)

<<Hive編程指南>>讀書筆記

1. 設置hive以本地模式運行(即便當前用戶是在分佈式模式或僞分佈式模式下執行也使用這種模式)

set hive.exec.model.local.auto=true;

若想默認使用這個配置,能夠將這個命令添加到$HOME/.hiverc文件中java

2. 當頻繁使用hadoop dfs命令時,最好爲這個命令定義一個別名

alias hdfs="hadoop dfs"

3. hive表數據默認存儲位置(基於hadoop的運行模式)

  • hadoop爲本地模式:file:///user/hive/warehouse
  • hadoop分佈式模式:hdfs://namenode_server/user/hive/warehouse

4. 用戶使用下面的命令能夠自定義數據倉庫的位置

set hive.metastore.warehouse.dir=/user/myname/hive/warehouse;

能夠將這條語句寫入到$HOME/.hiverc文件中node

5. 開啓在hive命令行中顯示當前數據庫名

set hive.cli.print.current.db=true;

6. hive -S 靜默輸出,在標準輸出中不顯示其餘信息

  • hive -e 後面直接跟HiveQL正則表達式

  • hive -S -e "select name from person;"shell

Hive會將輸出寫到標準輸出中,可使用shell中的輸出重定向將輸出重定向到本地文件中,而不是hdfs中數據庫

7. hive模糊取某個屬性名

hive -S -e "set" | grep warehouse 查詢數據倉庫的位置

8. 從文件中執行Hive查詢

hive -f /user/scott/hive.hql

或者在hive shell中使用source命令來執行腳本文件apache

hive > source /user/scott/hive.hql

9. hiverc文件

hive啓動後默認會在當前用戶home目錄下尋找名爲.hiverc的文件,且自動執行文件中的命令編程

一個典型的.hiverc文件中的內容爲安全

ADD JAR /user/scott/hive-examples.jar;   #增長一個jar文件
set hive.cli.print.current.db=true;     #顯示當前所在工做數據庫
set hive.exec.model.local.auto=true;    #設置以本地文件模式運行(當hadoop是以分佈式模式或者僞分佈式模式執行時的話,就在本地執行,能夠加快小數據集的查詢速度)

注:每行語句結尾的分號不可省略session

10. 在hive shell中執行shell命令

用戶不須要退出hive就能夠執行shell命令,只須要在命令前加上!而且以;結尾就能夠,如:app

hive > !pwd;  #查看當前目錄

注:hive shell中使用shell命令時,不能使用須要用戶進行輸入交互的命令,且不支持shell的管道功能和文件名自動補全功能。

11. 在hive中使用hadoop命令

hive > dfs -ls /;

12. hive腳本中的註釋

-- 用戶使用以--開頭的字符表示註釋。該註釋只能放在hiveql腳本中若直接在hive shell中使用的話會報錯

13. 讓cli顯示字段名稱

hive > set hive.cli.print.header=true;

同理能夠將該語句添加到$home/.hiverc文件中

14. Hive中的數據庫

若是用戶沒有顯式指定數據庫,默認數據庫是default

下面這個例子展現瞭如何建立數據庫

CREATE DATABASE simple;

若數據庫simple已經存在的話,將會報錯誤消息。可使用下面的語句避免錯誤信息

CREATE DATABASE IF NOT EXISTS simple;

使用SHOW DATABASES命令查看hive中所包含的數據庫

SHOW DATABASES;

若是數據庫比較多,可使用正則表達式匹配篩選所須要的數據庫名

SHOW DATABASES LIKE 'sim.*';

Hive爲每一個數據庫建立一個目錄,數據庫中的表將會以這個數據庫目錄的子目錄形式存儲。有一個例外就是default數據庫中的表。由於這個數據庫自己沒有本身的目錄。數據庫所在的目錄位於屬性hive.metastore.warehouse.dir所指定的頂層目錄以後。倘若用戶使用的這個配置項的默認配置,也就是/user/hive/warehouse,那麼當咱們建立數據庫simple時,Hive將會對應地建立一個目錄爲/user/hive/warehouse/simple.db。這裏請注意,數據庫的文件目錄名是以.db結尾的。

用戶能夠經過以下的命令來修改這個默認的配置

hive > CREATE DATABASE simple LOCATION '/user/myname/directory';

用戶還能夠爲這個數據庫增長一個描述信息。這樣經過DESCRIBE DATABASE databasename命令就能夠查看到該信息

hive > CREATE DATABASE simple COMMENT 'a simple database';

使用DESCRIBE DATABASE databasename查看

hive > DESCRIBE DATABASE simple;
simple a simple database
	hdfs://hostname/user/hive/warehouse/simple.db

從上面的例子能夠看出DESCRIBE DATABASE不只會顯示這個數據庫的描述信息還會顯示這個數據庫所在文件的目錄位置。若Hadoop是本地模式的話前面的前綴爲file:///如果分佈式模式則前綴爲hdfs://

此外用戶還能夠爲數據庫增長一些和其餘相關的鍵-值對屬性信息。可使用DESCRIBE DATABASE EXTENDED databasename語句顯示這些信息,如:

hive > CREATE DATABASE simple WITH DBPROERTIES ('creator'='scott','date'='2014-05-05');
hive > DESCRIBE DATABASE simple;
hive > DESCRIBE DATABASE EXTENDED simple;

命令USE用於將某個數據庫設置爲當前的工做數據庫。如:

USE simple;

此時能夠用SHOW TABLES顯示當前數據庫下全部的表。不幸的是,沒有那個命令讓用戶查看當前所在的庫。幸運的是在Hive中能夠重複使用USE,這是由於在Hive中沒有嵌套數據庫的概念。

hive > set hive.cli.print.current.db=true;
hive (simple) > USE default;
hive (default) > set hive.cli.print.current.db=false;

最後用戶能夠刪除數據庫

hive > DROP DATABASE IF EXISTS simple;

IF EXISTS子句是可選的。能夠避免因數據庫不存在而拋出警告信息。默認狀況下Hive是不容許用戶刪除一個包含有表的數據倉庫。要麼用戶先刪除庫中的表,而後再刪數據庫。要麼在刪除命令的最後面加上關鍵字CASCADE,這樣Hive先自行刪除數據庫中的表

hive > DROP DATABASE IF EXISTS simple CASCADE;

若使用的是RESTRICT這個關鍵字,而不是CASCADE這個關鍵字的話,那麼就和默認狀況同樣。

若是某個數據庫被刪除了,那麼其對應的目錄也同時會被刪除。

15. 修改數據庫

用戶可使用ALTER DATABASE命令爲某個數據庫的DBPROPERTIES設置鍵-值對屬性值,來描述數據庫的屬性信息。數據庫的其餘元數據信息是不可更改的,包括數據庫名和數據庫所在的目錄位置。

hive > ALTER DATABASE simple SET DBPROPERTIES ('edited-by'='Join');

沒有辦法刪除或者"重置"數據庫屬性。

16. 建立表

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'
TBLPROPERTIES ('creator'='me', 'created_at'='2012-01-02 10:00:00')
LOCATION '/user/hive/warehouse/mydb.db/employees';

首先,咱們注意到,若是用戶當前所處的數據庫並不是是目標數據庫,那麼用戶是能夠在表名前增長一個數據庫名來進行指定的,也就是例子中的mydb

若是用戶增長上選項IF NOT EXISTS,那麼若表已經存在了,Hive就會忽略掉後面的執行語句。且不會有任何提示。用戶能夠在字段類型後使用COMMENT爲每一個字段增長一個註釋。還能夠指定一個或多個表屬性。大多數狀況下TBLPROPERTIES的主要做用是按鍵-值對的格式爲表增長額外的文檔說明。

Hive會自動增長兩個表屬性:一個是last_modified_by,其保存着最後修改這個表的用戶的用戶名;另外一個是last_modified_time其保存着最後一次修改這個表的新紀元時間秒。

使用SHOW TBLPROPERTIES table_name列舉出某個表的TBLPROPERTIES屬性信息

最後,能夠看到咱們根據狀況爲表中的數據指定一個存儲路徑。在這個例子中,咱們使用Hive默認的路徑/user/hive/warehouse/mydb.db/employees,其中,/user/hive/warehouse是默認的數據倉庫路徑,mydb.db是數據庫目錄,employees是表目錄。

默認狀況下。Hive老是將建立的表的目錄放置在這個表所屬的數據庫目錄之下。不過,default數據庫是個例外,其在/user/hive/warehouse下並無對應一個數據庫目錄。所以default數據庫中的表目錄會直接位於/user/hive/warehouse目錄下(用戶明確指定除外).

用戶還能夠拷貝一張已經存在的表的模式(無需拷貝數據):

CREATE TABLE IF NOT EXISTS mydb.employees2
LIKE mydb.employees;

該語句能夠接受可選的LOCATION子句,可是注意其餘的屬性,包括模式都是不可能從新定義的。這些信息直接從原是表得到.

SHOW TABLES命令能夠列舉出全部的表,若是不增長其餘參數,那麼只會顯示當前工做數據庫下的表。假設不在那麼數據庫下,仍是能夠列出指定數據庫下的表使用SHOW TABLES IN dbname

hive > USE default;
hive > SHOW TABLES IN mydb;
employees
department

若是有不少的表,那麼可使用正則表達式來過濾出所須要的表名.

hive> USE mydb;
hive> SHOW TABLES 'empl.*';
employees

注意:IN databasename和表名使用正則表達式過濾這個兩個功能尚不支持同時使用.

咱們可使用DESCRIBE EXTENDED mydb.employees命令來查看這個表的詳細結構信息(若是當前所處的工做數據庫就是mydb的話,能夠不加mydb這個前綴).

hive> DESCRIBE EXTENDED mydb.employees;
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 Table(tableName:employees, dbName:mydb, owner:me,
...
location:hdfs://master-server/user/hive/warehouse/mydb.db/employees,
parameters:{creator=me, created_at='2012-01-02 10:00:00',
last_modified_user=me, last_modified_time=1337544510,
comment:Description of the table, ...}, ...)

使用FORMATTED關鍵字替代EXTENDED關鍵字的話,能夠提供更加可讀的輸出信息。在應用中多使用FORMATTED關鍵字

DESCRIBE FORMATTED employees;

若是用戶只想查看某一個列的信息,那麼只要在表名後面增長這個字段的名稱便可.

hive> DESCRIBE mydb.employees.salary;
salary float Employee salary

注:last_modified_bylast_modified_time兩個表屬性是自動建立的。若是用戶沒有定義任何的自定義表屬性的話,那麼這兩個表屬性也不會顯示在表的詳細信息中!

17. 管理表

咱們目前所建立的表均屬於管理表,有時也被稱爲內部表.由於這種表,Hive會或多或少的控制着數據項的生命週期.如:Hive默認狀況下會將這些表的數據存儲在由配置項hive.metastore.warehouse.dir(如/user/hive/warehouse)所定義的目錄的子目錄下.

當咱們刪除一個管理表時,Hive也會刪除這個表中的數據.管理表不方便和其餘工做共享數據。

18. 外部表

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 EXTENDED tablename語句的輸出中查看到表是管理表仍是外部表.在末尾的詳細表信息輸出中,對於管理表,用戶能夠看到以下信息:

tableType:MANAGED_TABLE

對於外部表

tableType:EXTERNAL_TABLE

對於管理表,用戶能夠對一張存在的表進行結構複製(不會複製數據)

CREATE EXTERNAL TABLE IF NOT EXISTS mydb.employees3
LIKE mydb.employees
LOCATION '/path/to/data';

若語句中省略掉EXTERNAL關鍵字,且源表是外部表的話,那麼新生成的表也將是外部表,若語句中省略掉EXTERNAL關鍵字,且源表是管理表的話,那麼新生成的表也將是管理表。 若語句中含有EXTERNAL關鍵字,且源表是管理表的話,那麼生成的新表將是外部表。 即便在這種場景下,LOCATION子句一樣是可選的。

19. 分區表、管理表

Hive中有分區表的概念。分區表將數據以一種符合邏輯的方式進行組織。好比分層存儲。

CREATE TABLE employees (
name STRING,
salary FLOAT,
subordinates ARRAY<STRING>,
deductions MAP<STRING, FLOAT>,
address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT>
)
PARTITIONED BY (country STRING, state STRING);

若是表中的數據以及分區個數很是大的話,執行一個包含全部分區的查詢可能會觸發一個巨大的MapReduce任務。建議的安全措施是將Hive設置爲「strict」模式,這樣對分區表查詢WHERE子句沒有加分區過濾的話,將會禁止提交這個任務.能夠按照下面的語句將屬性設置爲「nonstrict」模式。

hive> set hive.mapred.mode=strict;

hive> SELECT e.name, e.salary FROM employees e LIMIT 100;
FAILED: Error in semantic analysis: No partition predicate found for
Alias "e" Table "employees"

hive> set hive.mapred.mode=nonstrict;

hive> SELECT e.name, e.salary FROM employees e LIMIT 100;

能夠經過使用SHOW PARTITIONS命令查看錶中存在的全部分區

hive> SHOW PARTITIONS employees;
...
Country=CA/state=AB
country=CA/state=BC
...
country=US/state=AL
country=US/state=AK

若是表中存在不少的分區,而只想查看是否存儲某個特定分區鍵的分區的話。能夠在這個命令上增長一個指定了一個或者多個特定分區字段值的PARTITION子句,進行過濾

hive> SHOW PARTITIONS employees PARTITION(country='US');
country=US/state=AL
country=US/state=AK
...
hive> SHOW PARTITIONS employees PARTITION(country='US', state='AK');
country=US/state=AK

DESCRIBE EXTENDED employees命令也會顯示出分區鍵

hive> DESCRIBE EXTENDED employees;
name string,
salary float,
...
address struct<...>,
country string,
state string
Detailed Table Information...
partitionKeys:[FieldSchema(name:country, type:string, comment:null),
FieldSchema(name:state, type:string, comment:null)],

在管理表中用戶能夠經過載入數據的方式建立分區。下面的例子將從本地目錄()載入數據到表中的時候.將會建立一個US和CA分區.用戶須要爲每一個分區字段指定一個值.注意在HiveQL中是如何引用HOME環境變量的:

LOAD DATA LOCAL INPATH '${env:HOME}/california-employees'
INTO TABLE employees
PARTITION (country = 'US', state = 'CA');

Hive將會建立這個分區對應的目錄/employees/country=US/state=CA$HOME/california-employees目錄下的文件將會被拷貝到上述分區目錄下。

20. 外部分區表

CREATE EXTERNAL TABLE IF NOT EXISTS log_messages (
hms INT,
severity STRING,
server STRING,
process_id INT,
message STRING)
PARTITIONED BY (year INT, month INT, day INT)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

分區外部表對LOCATION沒有要求,使用ALTER TABLE語句單獨進行增長分區.這個語句須要爲每個分區鍵指定一個值。如:

ALTER TABLE log_messages ADD PARTITION(year = 2012, month = 1, day = 2)
LOCATION 'hdfs://master_server/data/log_messages/2012/01/02';

Hive並不控制這些數據,即便表被刪除,數據也不會被刪除.

和分區管理表同樣.經過SHOW PARTITIONS查看外部表的分區。如:

hive> SHOW PARTITIONS log_messages;
...
year=2011/month=12/day=31
year=2012/month=1/day=1
year=2012/month=1/day=2
...

一樣,DESCRIBE EXTENDED log_messages語句會將分區鍵做爲表的模式一部分和partitionKeys列表的內容同時顯示

hive> DESCRIBE EXTENDED log_messages;
...
message string,
year int,
month int,
day int
Detailed Table Information...
partitionKeys:[FieldSchema(name:year, type:int, comment:null),
FieldSchema(name:month, type:int, comment:null),
FieldSchema(name:day, type:int, comment:null)],
...

這個輸出少了一個很是重要的信息.那就是分區數據實際存在的路徑.

經過如下方式查看分區數據所在路徑

hive> DESCRIBE EXTENDED log_messages PARTITION (year=2012, month=1, day=2);
...
location:s3n://ourbucket/logs/2011/01/02,
...

一般會使用分區外部表.

21. 自定義表的存儲格式

Hive默認的存儲格式是文本文件格式.能夠經過可選的子句STORED AS TEXTFILE顯式指定.同時用戶能夠在建立表的時指定各類各樣的分隔符.

CREATE TABLE employees (
name STRING,
salary FLOAT,
subordinates ARRAY<STRING>,
deductions MAP<STRING, FLOAT>,
address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT>
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\001'
COLLECTION ITEMS TERMINATED BY '\002'
MAP KEYS TERMINATED BY '\003'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;

注:TEXTFILE意味着全部字段都使用字母、數字、字符編碼,包括那麼國際字符集.Hive默認是使用不可見字符來做爲分隔符的。使用TEXTFILE意味着,每一行被認爲是一個單獨的記錄.可使用SEQUENCEFILERCFILE兩種文件格式來替換TEXTFILE.這兩種文件格式都是使用二進制編碼和壓縮來優化磁盤空間及I/O帶寬性能的。

記錄編碼是經過一個input format對象來控制的。Hive使用了一個名爲org.apache.hadoop.mapred.TextInputFormat的java類.

記錄的解析是由序列化/反序列化(SerDe)來控制的,對於TEXTFILEHive所使用的SerDeorg.apache.hadoop.hive.serde2.lazy.LazySimpleSerDejava類.

Hive使用一個叫作output format的對象將查詢輸出寫入到文件中或者輸出到控制檯.對於TEXTFILEHive所使用的輸出類爲org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat

可使用第三方的輸入輸出格式及SerDe,容許用戶自定義Hive自己不支持的其餘文件格式

CREATE TABLE kst
PARTITIONED BY (ds string)
ROW FORMAT SERDE 'com.linkedin.haivvreo.AvroSerDe'
WITH SERDEPROPERTIES ('schema.url'='http://schema_provider/kst.avsc')
STORED AS
INPUTFORMAT 'com.linkedin.haivvreo.AvroContainerInputFormat'
OUTPUTFORMAT 'com.linkedin.haivvreo.AvroContainerOutputFormat';

ROW FORMAT SERDE …指定了使用的SerDe。Hive提供了WITH SERDEPROPERTIES功能,容許用戶傳遞配置信息給SerDe。每一個屬性名稱和值都應該是帶引號的字符串.

STORED AS INPUTFORMAT … OUTPUTFORMAT分別定義了用於輸入和輸出格式的java類。若是要指定,必須對輸入和輸出格式都指定.

DESCRIBE EXTENDED table會列出輸入和輸出格式以及SerDe和SerDe所自帶的屬性信息。如:

hive> DESCRIBE EXTENDED kst
...
inputFormat:com.linkedin.haivvreo.AvroContainerInputFormat,
outputFormat:com.linkedin.haivvreo.AvroContainerOutputFormat,
...
serdeInfo:SerDeInfo(name:null,
serializationLib:com.linkedin.haivvreo.AvroSerDe,
parameters:{schema.url=http://schema_provider/kst.avsc})
...

22. 刪除表

DROP TABLE IF EXISTS employees;

對於管理表,表的元數據信息和表內的數據都被刪除

對於外部表,表的元數據信息會被刪除,可是表中的數據不會被刪除

23. 修改表

大多數的表屬性能夠經過使用ALTER TABLE語句來修改.該操做會修改元數據,但不會修改數據自己.用於修改表模式中的錯誤及分區路徑.

23.1 表重命名

ALTER TABLE log_messages RENAME TO logmsgs;

23.2 增長、修改和刪除表分區

增長表分區

ALTER TABLE log_messages ADD IF NOT EXISTS
PARTITION (year = 2011, month = 1, day = 1) LOCATION '/logs/2011/01/01'
PARTITION (year = 2011, month = 1, day = 2) LOCATION '/logs/2011/01/02'
PARTITION (year = 2011, month = 1, day = 3) LOCATION '/logs/2011/01/03'
...;

修改分區路徑

ALTER TABLE log_messages PARTITION(year = 2011, month = 12, day = 2)
SET LOCATION 's3n://ourbucket/logs/2011/01/02';

這個命令不會將數據從舊的路徑移走,也不會刪除舊的數據

刪除分區

ALTER TABLE log_messages DROP IF EXISTS PARTITION(year = 2011, month = 12, day = 2);

對於管理表分區內的數據和元數據會一塊兒被刪除。對應外部表,分區內的數據不會被刪除

23.3 修改列信息

能夠對字段重命名、修改其位置、類型或者註釋:

ALTER TABLE log_messages
CHANGE COLUMN hms hours_minutes_seconds INT
COMMENT 'The hours, minutes, and seconds part of the timestamp'
AFTER severity;

即便字段名和字段類型都沒有改變,也須要徹底指定舊的字段名。並給出新的字段名以及新的字段類型。若要將字段移動到第一個位置,只須要使用FIRST關鍵字替代AFTER other_column子句便可.

這個操做,只會修改元數據信息。要注意數據與模式匹配.

23.4 增長列

能夠在分區字段前增長新的字段到已有字段以後

ALTER TABLE log_messages ADD COLUMNS (
app_name STRING COMMENT 'Application name',
session_id LONG COMMENT 'The current session id');

23.5 刪除或者替換列

ALTER TABLE log_messages REPLACE COLUMNS (
hours_mins_secs INT COMMENT 'hour, minute, seconds from timestamp',
severity STRING COMMENT 'The message severity'
message STRING COMMENT 'The rest of the message');

23.6 修改表屬性

ALTER TABLE log_messages SET TBLPROPERTIES (
'notes' = 'The process id is no longer captured; this column is always NULL');

能夠增長附加的表屬性或者修改已經存在的表屬性。可是沒法刪除屬性。

23.7 修改存儲屬性

ALTER TABLE log_messages
PARTITION(year = 2012, month = 1, day = 1)
SET FILEFORMAT SEQUENCEFILE;

若是是分區表,須要使用PARTITION子句

ALTER TABLE table_using_JSON_storage
SET SERDE 'com.example.JSONSerDe'
WITH SERDEPROPERTIES (
'prop1' = 'value1',
'prop2' = 'value2');

23.8 衆多的修改表語句

ALTER TABLE … TOUCH語句用於觸發鉤子

ALTER TABLE log_messages TOUCH
PARTITION(year = 2012, month = 1, day = 1);

ALTER TABLE … ARCHIVE PARTITION將分區內的文件打成一個Hadoop壓縮包(HAR)文件.僅僅下降文件系統中的文件數和NameNode的壓力,不會減小存儲空間

ALTER TABLE log_messages ARCHIVE
PARTITION(year = 2012, month = 1, day = 1);

最後Hive提供了保護,下面的語句防止分區被刪除和被查詢

ALTER TABLE log_messages
PARTITION(year = 2012, month = 1, day = 1) ENABLE NO_DROP;
ALTER TABLE log_messages
PARTITION(year = 2012, month = 1, day = 1) ENABLE OFFLINE;
相關文章
相關標籤/搜索