本篇目錄:
1. Hive數據結構
2. DDL操作
3. DML操作
4. UDF函數
Hive數據結構
除了基本數據類型(與java類似),hive支持三種集合類型
Hive集合類型數據
array、map、structs
hive (default)> create table test( > name string, > friends array<string>, -- 創建array字段 > children map<string,int>, -- map字段 > address struct<street:string,city:string>) -- struct字段 > row format delimited -- 限制多個字段分段符 > fields terminated by ',' -- 字段之間以','分割 > collection items terminated by '_' -- 字段內部用'_'分割(包括array、map) > map keys terminated by ':' -- map內key-value用':' > lines terminated by '\n'; -- 不同行,用回車'\n'
按表格式,寫一份數據,傳到hdfs對應的hive-test表下,
Lili,bingbing_xinxin,Lucifa:18_Jack:19,Nanjing_Beijing
然后查詢數據庫,即可得到查詢結果;
test.name test.friends test.children test.address Lili ["bingbing","xinxin"] {"Lucifa":18,"Jack":19} {"street":"Nanjing","city":"Beijing"}
-
所以Hive的數據,一定是要按設計的格式,嚴格排列才能讀取的!!!
查詢集合數據
hive (default)> select friends[0] from test; -- 可以像java數組那樣訪問 OK bingbing
查詢map數據
hive (default)> select children['Lucifa'] from test; -- 只能用key來訪問 OK 18
查詢結構體數據
hive (default)> select address.street from test; -- address.street訪問 OK street Nanjing
DDL操作
庫、表的增刪改查
數據庫
-
創建數據庫
除了location參數,其他跟mysql一樣,支持like,desc
hive (default)> create database if not exists hive; OK -- 同時HDFS增加文件/user/hive/warehouse/hive.db hive (default)> create database if not exists hive location /hive; OK -- 自定義創建的數據庫在HDFS的路徑 -- 查看庫信息 hive (default)> desc database hive; OK db_name comment location owner_name owner_type parameters hive hdfs://master:9000/user/hive/warehouse/hive.db whr USER
-
修改數據庫
無法修改數據庫名和目錄位置;
alter
-
刪庫
-- 庫必須為空 hive (default)> drop database test; -- 強制刪除cascade hive (default)> drop database test cascade;
表
-
查看一下表信息
hive (default)> show create table test; CREATE TABLE `test`( `name` string, `friends` array<string>, `children` map<string,int>, `address` struct<street:string,city:string>) ROW FORMAT DELIMITED --分隔符 FIELDS TERMINATED BY ',' COLLECTION ITEMS TERMINATED BY '_' MAP KEYS TERMINATED BY ':' LINES TERMINATED BY '\n' STORED AS INPUTFORMAT --輸入格式 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT --輸出格式 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION --存儲位置 'hdfs://master:9000/user/hive/warehouse/test' TBLPROPERTIES ( 'transient_lastDdlTime'='1569750450')
-
內部表(管理表)、外部表
內部表:刪除,同時刪除元數據和hdfs數據;
外部表:刪除,只會刪除元數據信息,不刪hdfs數據;
修改student內部表為外部表:
alter table student set tblproperties('EXTERNAL'='TRUE');--后面必須大寫
修改外部表為內部表:
alter table student set tblproperties('EXTERNAL'='False');
查詢表類型
desc formatted student;
-
分區表
避免暴力掃描;
一個分區就是hdfs上的一個獨立文件夾;Hive的分區就是hdfs的目錄分割;
創建一個分區表:(在元數據PARTITIONS表中存有分區信息)
hive (default)> create table dept_partition( > deptno int,dname string, loc string) > partitioned by (month string) -- 以month分區,month默認也算作一個字段 > row format delimited fields terminated by '\t';
加載數據:
load data [local] inpath 'path' [overwrite] into table [partition_psc]; local: 有==>從linux本地加載數據 無==>從hdfs加載數據,相當於執行mv操作(無指的是沒有local參數時,而不是本地中沒有這個文件) overwrite 有==>覆蓋掉表中原來的數據 無==>在原來的基礎上追加新的數據
查詢:
-- 分區查詢where hive (default)> select * from dept_partition where month = '2019-9-31';
單獨添加分區
-- 可添加多個分區 hive (default)> alter table dept_partition add partition(month='2019-9-29') partition(month='2019-9-28');
刪除分區
-- add改成drop,每個分區間加 ',' hive (default)> alter table dept_partition drop partition(month='2019-9-29'),partition(month='2019-9-28');
查看有多少分區
hive (default)> show partitions dept_partition;
-
其實就是以兩個字段來分區
hive (default)> create table dept_2( > deptno int,dname string,loc string) > partitioned by (month string,day string) > row format delimited fields terminated by '\t';
上傳數據
在hdfs是顯示兩層目錄:/user/hive/warehouse/dept_2/month=2019-9/day=30/dept.txt
-- 這里分區,要寫兩個 hive (default)> load data local inpath '/home/whr/Desktop/dept.txt' into table dept_2 partition(month='2019-9',day='30');
-
分區表的數據加載的三種方式:
(1)load命令,自動創建文件夾,以及元數據;(常用)
(2)手動添加分區文件夾以及分區數據,需要修復元數據,才能查詢;(了解)
這里會自動根據hdfs文件,來修復,如果說存在大量的沒有元數據的數據,可以用此命令;
hive (default)> msck repair table dept_parition;
(3)手動添加分區文件夾以及分區數據,使用添加分區命令,自動補充元數據;(常用)
第三種例子:
# 通過hadoop命令,創建了文件夾,並上傳數據 $ hadoop fs -mkdir -p /user/hive/warehouse/dept_partition/month=2019-9-17 $ hadoop fs -put '/home/whr/Desktop/dept.txt' /user/hive/warehouse/dept_partition/month=2019-9-17
添加分區
-- 添加分區 hive (default)> alter table dept_partition add partition(month='2019-9-17'); OK Time taken: 0.1 seconds -- 查詢所有分區 hive (default)> show partitions dept_partition; OK partition month=2019-9-17 --存在 month=2019-9-30 month=2019-9-31
DML數據操作
-
添加數據:
(1)load
(2)insert(不管數據是否重復,只管追加,多次insert,追加重復數據)
hive (default)> insert into table test > select id,name from mess; -- 從mess表查詢,插入test -- 會執行MR程序 2019-09-30 14:53:55,879 Stage-1 map = 0%, reduce = 0% 2019-09-30 14:54:01,365 Stage-1 map = 100%, reduce = 0%, Cumulative CPU 2.68 sec
(3)overwrite(重復->覆蓋;不重復->追加)
hive (default)> insert overwrite table test > select * from mess;
(4)as select(在創建表的時候,導入數據)
hive (default)> create table pika > as select id,name from test;
(5)location(創建的時候通過location,指定加載數據路徑)
hive (default)> create table jieni( > id int,name string) > location 'user/hive/warehouse/mess/dept.txt'; --hdfs文件目錄
(6)import(講數據導入Hive表中,很少用,前提有export數據,需要export的數據格式)
-
必須列完全相同並且是個空表,才能導入;
-
-
數據導出
-- 導出到本地,也可以導出到hdfs(刪掉local) hive (default)> insert overwrite local directory '/home/whr/Desktop/data' select * from test; -- 導出數據為一個目錄,數據在000000_0文件中,並且沒有分隔符
(2)用hadoop命令,下載數據
(3)export導出(少用)
(4)sqoop導出:實現MySql和HDFS(Hive)數據之間導入導出;
-
清空表:truncate
只會清除數據,表結構不變,只能刪除內部表(管理表),不能刪除外部表
至於查詢操作,基本上與MySql一致,不再贅述;
自定義函數UDF
可以分為三種:
-
UDF:自定義函數;一進一出
public class MyUDF extends UDF { public int evaluate(int data){ return data+5; } }
-
UDTF:自定義Table函數;一進多出;
public class MyUDTF extends GenericUDTF { private List<String> dataList = new ArrayList<>(); // 定義輸出數據的列名和數據類型 @Override public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException { // 定義輸出數據的列名 List<String> fieldName = new ArrayList<>(); fieldName.add("word"); // 定義輸出數據的類型 List<ObjectInspector> fieldOIs = new ArrayList<>(); fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector); // return ObjectInspectorFactory.getStandardStructObjectInspector(fieldName, fieldOIs); } /** * 函數處理邏輯:函數需要兩個參數: * 1.args[0]:一個字符數組, * 2.args[1]:字符數組的分隔符 * 使用方法:select myudtf('hello,word,qqq,new',','); */ @Override public void process(Object[] args) throws HiveException { /** * 1.獲取數據 * 2.獲取分隔符 * 3.切分數據 * 4.輸出數據 */ String data = args[0].toString(); String splitKey = args[1].toString(); String[] words = data.split(splitKey); for (String word : words) { dataList.clear(); dataList.add(word); forward(dataList); } } @Override public void close() throws HiveException { } }
-
UDAF:自定義聚合函數;多進一出;
使用:
# 添加jar包,建議添加到hive/lib下,不需要add,可以直接使用 hive (default)> add jar /home/whr/Desktop/notes/Hadoop_notes/Hive_code/target/MyUDTF.jar; # 創建函數 hive (default)> create function myudtf as 'UDF.MyUDTF'; # 傳參 hive (default)> select myudtf('hello,word,qqq,new',','); OK word # 這里是自定義的列名 hello word qqq new