004-hive基本操作
阿新 • • 發佈:2018-11-26
文章目錄
hive 基本操作
1、資料庫的基本操作
1)預設的資料庫是 default 2)建立資料庫:create database hivedb comment 'I am hive database'; 完整格式: create database|schema [if not exists] database_name [comment database_comment] [location hdfs_path] [with dbproperties (property_name=property_value, ...)]; 設定一些屬性 建立資料庫使用 database 或 schema 都可以; if not exists:判斷資料庫是否存在; comment:資料庫註釋; location hdfs_path:指定資料庫在 hdfs 上的目錄,預設/user/hive/warehouse/database_name; with dbproperties (property_name=property_value, ...):設定一些屬性 例:create database hivetestdb; # 建立資料庫,Hive會在/user/hive/warehouse/下建立一個以database_name.db命名的目錄(如:/user/hive/warehouse/hivetestdb.db) 3)檢視所有資料庫:show databases; 4)檢視指定資料庫:desc database database_name; 5)檢視指定資料庫詳細資訊:desc database extended database_name; 6)檢視當前資料庫:select current_database(); 7)切換資料庫:use database_name; 8)刪除空資料庫:drop database database_name; 級聯刪除資料庫(包括表):drop database database_name cascade; 刪除資料庫完善格式:drop database if exists database_name cascade;
2、表的操作
操作 hive 表時,最好在前面加上資料庫名 1)建立表:create database auser(id int comment 'I am id',name varchar(30)); 建立表時指定分隔符:create database auser(id int comment 'I am id',name varchar(30)) [row format delimited fields terminated by '\t']; 建立帶分割槽的表:CREATE TABLE tab01 (id int,name string) PARTITIONED BY (ds string); 不指定 database 時,預設建立在 default 資料庫中; 說明:在 hivetestdb 中建立表 auth_user,hive 會在 /user/hive/warehouse/hivetestdb.db 下建立 auth_user 目錄。 2)查看錶資料:select * from table_name; 3)檢視當前庫所有表:show tables; 4)檢視建表語句:show create table table_name; 5)檢視一個表的分割槽:show partition table_name; 如果這個表不存在分割槽則會報錯 6)查看錶結構(包括註釋):describe table_name 或 desc table_name 或 desc formatted table_name; 例: describe extended utab2; 輸出: Table( tableName : utab2, dbName : default, owner : root, createTime : 1537504392, lastAccessTime : 0, retention : 0, sd : StorageDescriptor( cols : [ FieldSchema(name : id,type : int,comment : null), FieldSchema(name : uname,type : string,comment : null), FieldSchema(name : age,type : int,comment : null) ], location : hdfs://localhost:9000/user/hive/warehouse/utab2, inputFormat : org.apache.hadoop.mapred.TextInputFormat, outputFormat : org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat, compressed : false, numBuckets : -1, serdeInfo : SerDeInfo(name : null, serializationLib : org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, parameters : {serialization.format=1}), bucketCols : [], sortCols : [], parameters : {}, skewedInfo : SkewedInfo(skewedColNames : [], skewedColValues : [], skewedColValueLocationMaps : {}), storedAsSubDirectories : false ), partitionKeys : [], parameters : { totalSize=8, numRows=1, rawDataSize=7, COLUMN_STATS_ACCURATE={\"BASIC_STATS\" : \"true\",\"COLUMN_STATS\" : {\"age\" : \"true\",\"id\" : \"true\",\"uname\" : \"true\"}}, numFiles=1, transient_lastDdlTime=1537505000, bucketing_version=2 }, viewOriginalText : null, viewExpandedText : null, tableType : MANAGED_TABLE, rewriteEnabled : false, catName : hive, ownerType : USER ) 7)查看錶詳細資訊:describe extended table_name; 8)修改表 a. 修改表名:alter table table_name rename to new_table_name; b. 修改 location:alter table table_name set location 'hdfs://nameservice1/data/test'; c. 修改表屬性(如編碼):alter table table_name set serdeproperties('serialization.encoding'='GBK'); d. 新增列:alter table table_name add columns (age int comment 'this is age'); e. 使用新欄位覆蓋表原所有欄位:alter table table_name replace columns (age string comment 'only keep the column'); 9)刪除和清空表 a. 刪除表:drop table [if exists] table_name; b. 清空表:truncate table table_name; 注意: 》truncate table student; 只能對管理表使用,不能對外部表使用 》truncate 命令操作時表名前不能加上database_name 》外部表 drop 之後,資料表在hdfs上目錄的資料檔案依然存在,實際是隻刪除了儲存在關係型資料庫中的元資料 》管理表 truncate 之後,資料表location 所在目錄的資料檔案刪除,目錄依然存在。 管理表 drop 之後,資料表location 所在目錄刪除。刪除了元資料和資料檔案,資料目錄。 10)插入資料 a. 單表插入 insert overwrite table tab09 select a.* from tab03 a; insert overwrite table tab09 select 7,'cat'; insert into table auth_user values (4,'kitty'); 說明: overwrite 是覆蓋,into 是追加。 b. 多表插入(Multi Table/File Inserts) FROM src INSERT OVERWRITE TABLE dest1 SELECT src.* WHERE src.key < 100 INSERT OVERWRITE TABLE dest2 SELECT src.key, src.value WHERE src.key >= 100 and src.key < 200 INSERT OVERWRITE TABLE dest3 PARTITION(ds='2008-04-08', hr='12') SELECT src.key WHERE src.key >= 200 and src.key < 300 INSERT OVERWRITE LOCAL DIRECTORY '/tmp/dest4.out' SELECT src.value WHERE src.key >= 300; FROM pv_users INSERT OVERWRITE TABLE pv_gender_sum SELECT pv_users.gender, count_distinct(pv_users.userid) GROUP BY pv_users.gender INSERT OVERWRITE DIRECTORY '/user/data/tmp/pv_age_sum' SELECT pv_users.age, count_distinct(pv_users.userid) GROUP BY pv_users.age; 【Dynamic-Partition Insert -- version 0.6.0 後增加的新特徵】 FROM page_view_stg pvs INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country='US') SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip WHERE pvs.country = 'US' INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country='CA') SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip WHERE pvs.country = 'CA' INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country='UK') SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip WHERE pvs.country = 'UK'; 上面這個語句,是一個非常不好的示例,因為我們預先需要知道所有的 country,並且 dt 如果變了,那麼我們需要重新增加新的 insert 語句。例如,當還有另外一個 country='DC' 或者 dt = '2008-09-10' Dynamic-partition insert 是為了解決上述問題而被設計的。所以 Dynamic-partition insert 如下即可 FROM page_view_stg pvs INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country) SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip, pvs.country 說明: 上述示例語句中,dt 是一個靜態分割槽列(因為它的值一直都是2008-06-08,沒有任何變化),country 是動態分割槽列。 動態分割槽列的值來自輸入列。 目前,只允許動態分割槽列作為分割槽子句中的最後一列(s),因為分割槽列順序表示它的層次順序,所以不能用(dt, country='US')來指定分割槽子句。 select 語句中額外增加的 pvs.country 列,是動態分割槽列對應的輸入列。請注意,您不需要為靜態分割槽列新增一個輸入列,因為它的值已經在隔斷子句中知道了。 注意,動態分割槽值是通過排序、而不是名稱來選擇的,並作為select子句的最後一列來選擇。(即動態分割槽列的值是來自 select 子句的最後一列,而不通過名字匹配的) 動態分割槽插入語句的語義: 當動態分割槽列已經存在非空分割槽時(例如,在某些ds根分割槽之下存在著country='CA'),如果動態分割槽插入在輸入資料中看到相同的值(比如'CA'),就會被覆蓋。 因為 Hive 分割槽對應於HDFS中的一個目錄,所以分割槽值必須符合HDFS路徑格式。任何在URI中具有特殊含義的字元(例如,'%', ':', '/', '#')都將以'%'的形式轉義,後跟2位元組的ASCII值。 如果輸入列是非字串的型別,那麼它的值將首先被轉換成字串,用於構造HDFS路徑。 如果輸入列值為NULL或空字串,這一行將被放入一個特殊的分割槽中,該分割槽的名稱由hive引數hive.exec.default.default.name控制。預設值是HIVE_DEFAULT_PARTITION{}。基本上這個分割槽將包含所有的“壞”行,它們的值不是有效的分割槽名稱。這種方法的警告是,如果您選擇Hive,那麼它將丟失並被HIVE_DEFAULT_PARTITION{}所取代。JIRA hia-1309是一個解決方案,讓使用者指定“壞檔案”來保留輸入分割槽列值。 動態分割槽插入可能是一個資源佔用者,因為它可以在短時間內生成大量的分割槽。為了讓自己分桶,我們定義了三個引數: hive.exec.max.dynamic.partitions.pernode:(預設值是1000)是每個mapper或reducer可以建立的最大動態分割槽數。如果一個mapper或reducer建立的比這個閾值更多,那麼將會從map/reducer(通過計數器)中產生一個致命的錯誤,整個job將被殺死。 hive.exec.max.dynamic.partitions:(預設值是100)能夠被一個DML建立的動態分割槽的總數。如果每一個mapper/reducer都沒有超過限制,但是動態分割槽的總數是超過了,那麼在將中間資料移動到最終目的地之前,將會丟擲一個異常結束 job。 hive.exec.max.created.files:(預設值是100000)是所有的mapper和reducer建立的最大的檔案總數。每一個mapper/reducer 建立一個新檔案時將執行 Hadoop counter 更新。如果總數超過了hive.exec.max.created.files,將丟擲一個致命的錯誤,job 將被殺死。 我們想要保護不利於動態分割槽插入的另一種情況是,使用者可能意外地指定所有分割槽為動態分割槽,而不指定一個靜態分割槽,雖然最初的目的是想覆蓋一個根分割槽的子分割槽。我們可以定義另外一個引數 hive.exec.dynamic.partition.mode=strict 來保護這種全動態分割槽情況。在嚴格模式下,您必須指定至少一個靜態分割槽。預設模式是嚴格的。另外,我們可以用一個引數 hive.exec.dynamic.partition=true/false 來控制是否允許動態分割槽。在Hive 0.9.0之前預設值是false,在Hive 0.9.0和之後預設值是 true。 在Hive 0.6中,hive.merge.mapfiles=true or hive.merge.mapredfiles=true時動態分割槽插入不工作。所以它內部關閉了merge 引數。在Hive 0.7中 merging file 是支援動態分割槽插入的(詳見JIRA hi1307)。
3、表的其他操作
1)group by CREATE TABLE tab10 (name string) row format delimited fields terminated by '\t'; a. select 語句為常規 sql INSERT OVERWRITE TABLE tab10 SELECT a.name FROM tab09 a GROUP BY a.name; b. from 寫到了 select 的前面 FROM tab09 a INSERT OVERWRITE TABLE tab10 SELECT a.name GROUP BY a.name; 2)Aggregations INSERT OVERWRITE TABLE pv_gender_sum SELECT pv_users.gender, count(DISTINCT pv_users.userid) FROM pv_users GROUP BY pv_users.gender; INSERT OVERWRITE TABLE pv_gender_agg SELECT pv_users.gender, count(DISTINCT pv_users.userid), count(*), sum(DISTINCT pv_users.userid) FROM pv_users GROUP BY pv_users.gender; 3)joins a. join FROM tab001 t1 JOIN tab002 t2 ON (t1.bar = t2.bar) INSERT OVERWRITE TABLE tab003 SELECT t1.bar, t1.foo, t2.foo; INSERT OVERWRITE TABLE pv_users SELECT pv.*, u.gender, u.age FROM user u JOIN page_view pv ON (pv.userid = u.id) WHERE pv.date = '2008-03-03'; b. LEFT OUTER, RIGHT OUTER or FULL OUTER,外部連線 INSERT OVERWRITE TABLE pv_users SELECT pv.*, u.gender, u.age FROM user u FULL OUTER JOIN page_view pv ON (pv.userid = u.id) WHERE pv.date = '2008-03-03'; c. LEFT SEMI JOIN,為了檢查另一張表中的鍵的存在,使用者可以使用左半連線,如下面的例子所示 INSERT OVERWRITE TABLE pv_users SELECT u.* FROM user u LEFT SEMI JOIN page_view pv ON (pv.userid = u.id) WHERE pv.date = '2008-03-03'; d. 多表連線 INSERT OVERWRITE TABLE pv_friends SELECT pv.*, u.gender, u.age, f.friends FROM page_view pv JOIN user u ON (pv.userid = u.id) JOIN friend_list f ON (u.id = f.uid) WHERE pv.date = '2008-03-03'; 4)Sampling -- 抽樣 從pv_gender_sum的32個桶中選擇第三個桶 INSERT OVERWRITE TABLE pv_gender_sum_sample SELECT pv_gender_sum.* FROM pv_gender_sum TABLESAMPLE(BUCKET 3 OUT OF 32); 5)Union All INSERT OVERWRITE TABLE actions_users SELECT u.id, actions.date FROM ( SELECT av.uid AS uid FROM action_video av WHERE av.date = '2008-06-03' UNION ALL SELECT ac.uid AS uid FROM action_comment ac WHERE ac.date = '2008-06-03' ) actions JOIN users u ON(u.id = actions.uid); 6)Custom Map/Reduce Scripts -- 自定義 Map/Reduce 指令碼 https://cwiki.apache.org/confluence/display/Hive/Tutorial#Tutorial-BuiltInOperatorsandFunctions FROM ( FROM pv_users MAP pv_users.userid, pv_users.date USING 'map_script' AS dt, uid CLUSTER BY dt) map_output INSERT OVERWRITE TABLE pv_users_reduced REDUCE map_output.dt, map_output.uid USING 'reduce_script' AS date, count; 7)streaming FROM invites a INSERT OVERWRITE TABLE events SELECT TRANSFORM(a.foo, a.bar) AS (oof, rab) USING '/bin/cat' WHERE a.ds > '2008-08-09';
4、hive匯入資料
1)table --> table
a. 匯入其他表資料
insert overwrite|into table table_name select * from table_name2;
b. 建立表時匯入其他表資料
create table table_name as select * from table_name2;
c. 建立表時指定 location,並匯入其他表資料
注意:建立表指定 location 匯入資料時必須是不存在的目錄,不然建立表會失敗。可以先建立表,再刪除相應的目錄,再將資料上傳到對應的目錄。表就可以直接加載出資料。
2)file --> table 將檔案內容匯入到表中(表所有目錄)
load data [local] inpath '/tmp/students.txt' [overwrite] into table table_name [partition(part1='value1',part2='value2',...)];
示例1:
load data local inpath '/tmp/students.txt' overwrite into table tab03;
說明:
local 表示載入本地資料;不使用 local 時,表示載入 HDFS 上的資料。
加上 overwrite 表示覆蓋,不加 overwrite 表示追加。
inpath 是載入的資料的目錄,一般寫全路徑。可以指定到檔案,也可以直接指定目錄,指定目錄會載入目錄下所有檔案的資料。
partition:向分割槽表中匯入資料。
示例2:
# local 用於指定本地檔案,如果缺省了,則會在 HDFS 中查詢檔案;OVERWRITE 表示覆蓋,如果預設則表示新增
load data local inpath '/tmp/students.txt' overwrite into table tab03;
# students.txt 內容為
id name
1 'zhangsan'
2 'lisi'
3 wangwu
# select * from tab03;
NULL name
1 'zhangsan'
2 'lisi'
3 wangwu
上面為 NULL 是因為第一列型別為 int
示例3:
CREATE TABLE tab07 (id int,name string) PARTITIONED BY (ds string) row format delimited fields terminated by '\t';
load data local inpath '/tmp/students.txt' overwrite into table tab07 PARTITION (ds='2008-08-15');
# students.txt
1 'zhangsan'
2 'lisi'
3 wangwu
4 tom
5 cat
6 kitty
select * from tab07;
1 'zhangsan' 2008-08-15
2 'lisi' 2008-08-15
3 wangwu 2008-08-15
4 tom 2008-08-15
5 cat 2008-08-15
6 kitty 2008-08-15
5、hive 匯出資料
1)table --> file
insert overwrite|into [local] directory '/temp/students.txt' [row format delimited fields terminated by '\t'] select * from table_name
示例:
# 往 HDFS 裡寫資料
insert overwrite directory '/tmp/students.txt' select * from tab07 t where t.ds = '2008-08-15';
# 往本地檔案裡寫資料
insert overwrite local directory '/tmp/students5' select a.* from tab03 a;
insert overwrite local directory '/tmp/students6' select * from tab07 t where t.ds = '2008-08-15';
參考地址:
https://cwiki.apache.org/confluence/display/Hive/Tutorial
https://www.cnblogs.com/johnny-YJL/p/7940594.html