一、基本操作
1.DDL
官網的DDL語法教程:點擊查看
建表語句
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name [(col_name data_type [COMMENT col_comment], ...)] [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] [ROW FORMAT row_format]
[STORED AS file_format]
[LOCATION hdfs_path]

data_type : primitive_type | array_type | map_type | struct_type | union_type -- (Note: Available in Hive 0.7.0 and later) primitive_type : TINYINT | SMALLINT | INT | BIGINT | BOOLEAN | FLOAT | DOUBLE | DOUBLE PRECISION -- (Note: Available in Hive 2.2.0 and later) | STRING | BINARY -- (Note: Available in Hive 0.8.0 and later) | TIMESTAMP -- (Note: Available in Hive 0.8.0 and later) | DECIMAL -- (Note: Available in Hive 0.11.0 and later) | DECIMAL(precision, scale) -- (Note: Available in Hive 0.13.0 and later) | DATE -- (Note: Available in Hive 0.12.0 and later) | VARCHAR -- (Note: Available in Hive 0.12.0 and later) | CHAR -- (Note: Available in Hive 0.13.0 and later) array_type : ARRAY < data_type > map_type : MAP < primitive_type, data_type > struct_type : STRUCT < col_name : data_type [COMMENT col_comment], ...> union_type : UNIONTYPE < data_type, data_type, ... > -- (Note: Available in Hive 0.7.0 and later)
說明:
1、CREATE TABLE 創建一個指定名字的表。如果相同名字的表已經存在,則拋出異常;用戶可以用 IF NOT EXISTS 選項來忽略這個異常。
2、EXTERNAL關鍵字可以讓用戶創建一個外部表,在建表的同時指定一個指向實際數據的路徑(LOCATION),Hive 創建內部表時,會將數據移動到數據倉庫指向的路徑;若創建外部表,僅記錄數據所在的路徑,不對數據的位置做任何改變。在刪除表的時候,內部表的元數據和數據會被一起刪除,而外部表只刪除元數據,不刪除數據。
3、LIKE 允許用戶復制現有的表結構,但是不復制數據。
4、ROW FORMAT
DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char]
[MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
| SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
用戶在建表的時候可以自定義 SerDe 或者使用自帶的 SerDe序列化工具。如果沒有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,將會使用自帶的 SerDe。在建表的時候,用戶還需要為表指定列,用戶在指定表的列的同時也會指定自定義的 SerDe,Hive通過 SerDe 確定表的具體的列的數據。
5、STORED AS
SEQUENCEFILE|TEXTFILE|RCFILE
如果文件數據是純文本,可以使用 STORED AS TEXTFILE。如果數據需要壓縮,使用 STORED AS SEQUENCEFILE。
6、CLUSTERED BY
對於每一個表(table)或者分區, Hive可以進一步組織成桶,也就是說桶是更為細粒度的數據范圍划分。Hive也是 針對某一列進行桶的組織。Hive采用對列值哈希,然后除以桶的個數求余的方式決定該條記錄存放在哪個桶當中。
把表(或者分區)組織成桶(Bucket)有兩個理由:
(1)獲得更高的查詢處理效率。桶為表加上了額外的結構,Hive 在處理有些查詢時能利用這個結構。具體而言,連接兩個在(包含連接列的)相同列上划分了桶的表,可以使用 Map 端連接 (Map-side join)高效的實現。比如JOIN操作。對於JOIN操作兩個表有一個相同的列,如果對這兩個表都進行了桶操作。那么將保存相同列值的桶進行JOIN操作就可以,可以大大較少JOIN的數據量。
(2)使取樣(sampling)更高效。在處理大規模數據集時,在開發和修改查詢的階段,如果能在數據集的一小部分數據上試運行查詢,會帶來很多方便。
示例:
CREATE TABLE page_view(viewTime INT, userid BIGINT, page_url STRING, referrer_url STRING, ip STRING COMMENT 'IP Address of the User') COMMENT 'This is the page view table' PARTITIONED BY(dt STRING, country STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\001' STORED AS SEQUENCEFILE;
重命名表
ALTER TABLE table_name RENAME TO new_table_name
增加/更新列
ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...) 注:ADD是代表新增一字段,字段位置在所有列后面(partition列前),REPLACE則是表示替換表中所有字段。 ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name]
2.DML
Load
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO
TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
說明:
1、 Load 操作只是單純的復制/移動操作,將數據文件移動到 Hive 表對應的位置。
2、 filepath:
相對路徑,例如:project/data1
絕對路徑,例如:/user/hive/project/data1
包含模式的完整 URI,列如:
hdfs://namenode:9000/user/hive/project/data1
3、 LOCAL關鍵字
如果指定了 LOCAL, load 命令會去查找本地文件系統中的 filepath。
如果沒有指定 LOCAL 關鍵字,則根據inpath中的uri查找文件
4、 OVERWRITE 關鍵字
如果使用了 OVERWRITE 關鍵字,則目標表(或者分區)中的內容會被刪除,然后再將 filepath 指向的文件/目錄中的內容添加到表/分區中。
如果目標表(分區)已經有一個文件,並且文件名和 filepath 中的文件名沖突,那么現有的文件會被新文件所替代。
insert
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement Multiple inserts: FROM from_statement INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 [INSERT OVERWRITE TABLE tablename2 [PARTITION ...] select_statement2] ... Dynamic partition inserts: INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement
select
SELECT [ALL | DISTINCT] select_expr, select_expr, ... FROM table_reference [WHERE where_condition]
[GROUP BY col_list [HAVING condition]] [CLUSTER BY col_list | [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list] ] [LIMIT number]
保存select 結果集的方式:
保存select查詢結果的幾種方式: 1、將查詢結果保存到一張新的hive表中 create table t_tmp as
select * from t_p; 2、將查詢結果保存到一張已經存在的hive表中 insert into table t_tmp select * from t_p; 3、將查詢結果保存到指定的文件目錄(可以是本地,也可以是hdfs) insert overwrite local directory '/home/hadoop/test'
select * from t_p; insert overwrite directory '/aaa/test'
select * from t_p;
3.hive join
join_table: table_reference JOIN table_factor [join_condition]
| table_reference {LEFT|RIGHT|FULL} [OUTER] JOIN table_reference join_condition | table_reference LEFT SEMI JOIN table_reference join_condition
Hive中除了支持和傳統數據庫中一樣的內關聯、左關聯、右關聯、全關聯,還支持LEFT SEMI JOIN和CROSS JOIN,但這兩種JOIN類型也可以用前面的代替。
左半連接這里給出一個示例,理論不贅述:參考:這里
1 SELECT a.id, 2 a.name 3 FROM lxw1234_a a 4 LEFT SEMI JOIN lxw1234_b b 5 ON (a.id = b.id); 6
7 --執行結果:
8 1 zhangsan 9 2 lisi 10
11 --等價於:
12 SELECT a.id, 13 a.name 14 FROM lxw1234_a a 15 WHERE a.id IN (SELECT id FROM lxw1234_b);
示例:
select * from a inner join b on a.id=b.id;
二、分區表與分桶表
1.分區表
在Hive Select查詢中一般會掃描整個表內容,會消耗很多時間做沒必要的工作。有時候只需要掃描表中關心的一部分數據,因此建表時引入了partition概念。分區表指的是在創建表時指定的partition的分區空間。
Hive可以對數據按照某列或者某些列進行分區管理,所謂分區我們可以拿下面的例子進行解釋。
當前互聯網應用每天都要存儲大量的日志文件,幾G、幾十G甚至更大都是有可能。存儲日志,其中必然有個屬性是日志產生的日期。在產生分區時,就可以按照日志產生的日期列進行划分。把每一天的日志當作一個分區。
將數據組織成分區,主要可以提高數據的查詢速度。至於用戶存儲的每一條記錄到底放到哪個分區,由用戶決定。即用戶在加載數據的時候必須顯示的指定該部分數據放到哪個分區。
建立分區表
create table t_user_part (id int, name string)
partitioned by (country string)
row format delimited fields terminated by '\t';
向分區表中導入數據

[hadoop@mini1 ~]$ cat user.dat 1 Join 2 Mary 3 Bob 4 Tom
LOAD DATA LOCAL INPATH '/home/hadoop/user.dat' INTO TABLE t_user_part PARTITION(country='USA');
0: jdbc:hive2://localhost:10000> SELECT * FROM t_user_part; +-----------------+-------------------+----------------------+--+
| t_user_part.id | t_user_part.name | t_user_part.country |
+-----------------+-------------------+----------------------+--+
| 1 | Join | USA |
| 2 | Mary | USA |
| 3 | Bob | USA |
| 4 | Tom | USA |
+-----------------+-------------------+----------------------+--+
4 rows selected (0.801 seconds) 0: jdbc:hive2://localhost:10000>
// 分區字段是一個偽字段
0: jdbc:hive2://localhost:10000> SELECT * FROM t_user_part WHERE country='USA';
增加分區
ALTER TABLE table_name ADD partition_spec [ LOCATION 'location1' ] partition_spec [ LOCATION 'location2' ] ... partition_spec: : PARTITION (partition_col = partition_col_value, partition_col = partiton_col_value, ...) 用戶可以用 ALTER TABLE ADD PARTITION 來向一個表中增加分區。當分區名是字符串時加引號。例: ALTER TABLE test_table ADD PARTITION (dt='2016-08-08', hour='10') location '/path/uv1.txt' PARTITION (dt='2017-08-08', hour='12') location '/path/uv2.txt';
刪除分區
ALTER TABLE table_name DROP partition_spec, partition_spec,... 用戶可以用 ALTER TABLE DROP PARTITION 來刪除分區。分區的元數據和數據將被一並刪除。例: ALTER TABLE test_table DROP PARTITION (dt='2016-08-08', hour='10');
查看分區
show partitions tablename
show partitions t_user_part;
分區的更多介紹以及動態分區的介紹與設置:https://www.cnblogs.com/liqiu/p/4095654.html
2.分桶表
- 對於每一個表(table)或者分區, Hive可以進一步組織成桶,也就是說桶是更為細粒度的數據范圍划分。(桶有點類似mr中的分區)Hive也是針對某一列進行桶的組織。Hive采用對列值哈希,然后除以桶的個數求余的方式決定該條記錄存放在哪個桶當中。基本可以這么說分區表是粗粒度的划分,桶在細粒度的划分。當數據量比較大,我們需要更快的完成任務,多個map和reduce進程是唯一的選擇。
-
但是如果輸入文件是一個的話,map任務只能啟動一個。此時bucket table是個很好的選擇,通過指定CLUSTERED的字段,將文件通過hash打散成多個小文件。
-
把表(或者分區)組織成桶(Bucket)有兩個理由:
-
獲得更高的查詢處理效率。桶為表加上了額外的結構,Hive 在處理有些查詢時能利用這個結構。具體而言,連接兩個在(包含連接列的)相同列上划分了桶的表,可以使用 Map 端連接 (Map-side join)高效的實現。比如JOIN操作。對於JOIN操作兩個表有一個相同的列,如果對這兩個表都進行了桶操作。那么將保存相同列值的桶進行JOIN操作就可以,可以大大較少JOIN的數據量。
-
使取樣(sampling)更高效。在處理大規模數據集時,在開發和修改查詢的階段,如果能在數據集的一小部分數據上試運行查詢,會帶來很多方便
注意:分桶之前要設置分桶開關以及reduce數量使其與分桶數量一致!
set hive.enforce.bucketing = true;
set mapreduce.job.reduces=4;
分桶表的相關操作,參考:http://www.mamicode.com/info-detail-1781619.html
建立分桶表:
create table t_buck(id int, name string) clustered by(id) sorted by(id) into 4 buckets row format delimited fields terminated by ',';
DESC EXTENDED t_buck;
裝載數據:此種方式不會自動分桶,需要自己提前分桶,不建議使用!
LOAD DATA LOCAL INPATH '/home/hadoop/user2.dat' INTO TABLE t_user_buck;
向這種帶桶的表里面導入數據有兩種方式,一種是外部生成的數據導入到桶表,一種是利用hive來幫助你生成桶表數據。
開始往創建的分通表插入數據(插入數據需要是已分桶, 且排序的)
可以使用distribute by(id) sort by(id asc)
排序和分桶的字段相同的時候也可以使用Cluster by(字段)
注意使用cluster by 就等同於分桶+排序(sort)
insert overwrite table t_buck select id,name from t_buck_from cluster by(id);
注:1、order by 會對輸入做全局排序,因此只有一個reducer,會導致當輸入規模較大時,需要較長的計算時間。 2、sort by不是全局排序,其在數據進入reducer前完成排序。因此,如果用sort by進行排序,
並且設置mapred.reduce.tasks>1,則sort by只保證每個reducer的輸出有序,不保證全局有序。 3、distribute by(字段)根據指定的字段將數據分到不同的reducer,且分發算法是hash散列。 4、Cluster by(字段) 除了具有Distribute by的功能外,還會對該字段進行排序。 5、創建分桶表並不意味着load進數據也是分桶的,你必須先分好桶,然后再放到表中。
0: jdbc:hive2://localhost:10000> dfs -cat /user/hive/warehouse/t_buck/000001_0; +-------------+--+
| DFS Output |
+-------------+--+
| 1,aa |
| 5,ee |
| 9,ii |
+-------------+--+
3 rows selected (0.032 seconds) 0: jdbc:hive2://localhost:10000>
分桶表的最大作用是提高了表之間的join效率,因為兩個分桶表之間join的字段只需對應桶即可!
具體分析與操作,參考:https://www.cnblogs.com/kouryoushine/p/7809299.html