Hive數(shù)據(jù)倉(cāng)庫(kù)基于shell命令行基本操作(DDL/DML):
首先啟動(dòng)hive數(shù)據(jù)庫(kù)倉(cāng)庫(kù)的shell腳本模式:
命令:/opt/mysoft/hive/bin/hive
1> 查看當(dāng)前Hive中有哪些數(shù)據(jù)庫(kù)
? ? ?hive初始化后,會(huì)生成一個(gè)默認(rèn)的default數(shù)據(jù)庫(kù);往往根據(jù)項(xiàng)目不同,會(huì)建立不同業(yè)務(wù)的hive數(shù)據(jù)庫(kù);
? ? ?命令:show databases;
2>?創(chuàng)建數(shù)據(jù)庫(kù)
? ? ?命令:create database test;?? ??
3>?打開(kāi)/使用數(shù)據(jù)庫(kù)
? ? ?命令:use test;
4> 查看數(shù)據(jù)庫(kù)中的所有表
? ? ?命令:show tables;
5>?基于打開(kāi)的數(shù)據(jù)庫(kù)建表
? ? ?命令:create table stu (id int,name string) ?row format delimited fields terminated by ',';
? ? ?查看創(chuàng)建成功后的表結(jié)構(gòu):
? ? ?命令:desc stu;
6>?加載數(shù)據(jù)到表中
? ? ?本地文件方式:
? ? ?命令:load data local inpath '/opt/mysoft/stu.txt' into table stu;??
? ? ?HDFS遠(yuǎn)程服務(wù)器方式:
? ? ?命令:load data inpath 'hdfs://hadoop:9000/output/*' into table stu;
語(yǔ)法命令:
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
?? [(col_name data_type[COMMENT col_comment], ...)]
?? [COMMENT table_comment]
?? [PARTITIONED BY (col_namedata_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]
1、 CREATE TABLE 創(chuàng)建一個(gè)指定名字的表。如果相同名字的表已經(jīng)存在,則拋出異常;用戶可以用 IF NOT EXISTS 選項(xiàng)來(lái)忽略這個(gè)異常。
2、 EXTERNAL關(guān)鍵字可以讓用戶創(chuàng)建一個(gè)外部表,在建表的同時(shí)指定一個(gè)指向?qū)嶋H數(shù)據(jù)的路徑(LOCATION)。
Hive 創(chuàng)建內(nèi)部表時(shí),會(huì)將數(shù)據(jù)移動(dòng)到數(shù)據(jù)倉(cāng)庫(kù)指向的路徑;若創(chuàng)建外部表,僅記錄數(shù)據(jù)所在的路徑,不對(duì)數(shù)據(jù)的位置做任何改變。在刪除表的時(shí)候,內(nèi)部表的元數(shù)據(jù)和數(shù)據(jù)會(huì)被一起刪除,而外部表只刪除元數(shù)據(jù),不刪除數(shù)據(jù)。
3、 LIKE 允許用戶復(fù)制現(xiàn)有的表結(jié)構(gòu),但是不復(fù)制數(shù)據(jù)。
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name LIKE existing_table;
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,...)]
hive建表的時(shí)候默認(rèn)的分割符是'\001',若在建表的時(shí)候沒(méi)有指明分隔符,load文件的時(shí)候文件的分隔符需要是'\001';若文件分隔符不是'001',程序不會(huì)報(bào)錯(cuò),但表查詢的結(jié)果會(huì)全部為'null';
用vi編輯器Ctrl+v然后Ctrl+a即可輸入'\001' ----------->? ^A
SerDe是Serialize/Deserilize的簡(jiǎn)稱,目的是用于序列化和反序列化。
Hive讀取文件機(jī)制:首先調(diào)用InputFormat(默認(rèn)TextInputFormat),返回一條一條記錄(默認(rèn)是一行對(duì)應(yīng)一條記錄)。然后調(diào)用SerDe(默認(rèn)LazySimpleSerDe)的Deserializer,將一條記錄切分為各個(gè)字段(默認(rèn)'\001')。
Hive寫文件機(jī)制:將Row寫入文件時(shí),主要調(diào)用OutputFormat、SerDe的Seriliazer,順序與讀取相反。
可通過(guò)desc formatted 表名;進(jìn)行相關(guān)信息查看。
當(dāng)我們的數(shù)據(jù)格式比較特殊的時(shí)候,可以自定義SerDe。
5、 PARTITIONED BY
在hive Select查詢中一般會(huì)掃描整個(gè)表內(nèi)容,會(huì)消耗很多時(shí)間做沒(méi)必要的工作。有時(shí)候只需要掃描表中關(guān)心的一部分?jǐn)?shù)據(jù),因此建表時(shí)引入了partition分區(qū)概念。
分區(qū)表指的是在創(chuàng)建表時(shí)指定的partition的分區(qū)空間。一個(gè)表可以擁有一個(gè)或者多個(gè)分區(qū),每個(gè)分區(qū)以文件夾的形式單獨(dú)存在表文件夾的目錄下。表和列名不區(qū)分大小寫。分區(qū)是以字段的形式在表結(jié)構(gòu)中存在,通過(guò)describe table命令可以查看到字段存在,但是該字段不存放實(shí)際的數(shù)據(jù)內(nèi)容,僅僅是分區(qū)的表示。
6、 STORED AS SEQUENCEFILE|TEXTFILE|RCFILE
如果文件數(shù)據(jù)是純文本,可以使用 STORED AS TEXTFILE。如果數(shù)據(jù)需要壓縮,使用 STORED AS SEQUENCEFILE。
TEXTFILE是默認(rèn)的文件格式,使用DELIMITED子句來(lái)讀取分隔的文件。
6、CLUSTERED BY INTO num_buckets BUCKETS
對(duì)于每一個(gè)表(table)或者分,Hive可以進(jìn)一步組織成桶,也就是說(shuō)桶是更為細(xì)粒度的數(shù)據(jù)范圍劃分。Hive也是針對(duì)某一列進(jìn)行桶的組織。Hive采用對(duì)列值哈希,然后除以桶的個(gè)數(shù)求余的方式?jīng)Q定該條記錄存放在哪個(gè)桶當(dāng)中。
把表(或者分區(qū))組織成桶(Bucket)有兩個(gè)理由:
(1)獲得更高的查詢處理效率。桶為表加上了額外的結(jié)構(gòu),Hive 在處理有些查詢時(shí)能利用這個(gè)結(jié)構(gòu)。具體而言,連接兩個(gè)在(包含連接列的)相同列上劃分了桶的表,可以使用 Map 端連接 (Map-side join)高效的實(shí)現(xiàn)。比如JOIN操作。對(duì)于JOIN操作兩個(gè)表有一個(gè)相同的列,如果對(duì)這兩個(gè)表都進(jìn)行了桶操作。那么將保存相同列值的桶進(jìn)行JOIN操作就可以,可以大大較少JOIN的數(shù)據(jù)量。
(2)使取樣(sampling)更高效。在處理大規(guī)模數(shù)據(jù)集時(shí),在開(kāi)發(fā)和修改查詢的階段,如果能在數(shù)據(jù)集的一小部分?jǐn)?shù)據(jù)上試運(yùn)行查詢,會(huì)帶來(lái)很多方便。
hive cli中顯示列名: 進(jìn)入hive cli后 set hive.cli.print.header=true;
案例:
1> 創(chuàng)建普通表,字段以逗號(hào)進(jìn)行分割,默認(rèn)分隔符是'\001', vi 編輯器的:ctrl + v 和 ctrl+a
create table tb_stu(id int, name string) row format delimited fields terminated by ',';?
2> 創(chuàng)建分區(qū)表,有時(shí)候數(shù)據(jù)量太大,我們只需要查詢一部分,可以使用字段分區(qū),分區(qū)字段不能和已有的字段重復(fù)
create table tb_stu2(id int,name string) partitioned by (age int) row format delimited fields terminated by ',';
加載數(shù)據(jù):load data local inpath '/opt/mysoft/hivedata/student.txt' INTO TABLE tb_stu2 PARTITION(age=20);
加載數(shù)據(jù)時(shí)如果添加local加載的是本地?cái)?shù)據(jù),如果沒(méi)有l(wèi)ocal加載的是hdfs服務(wù)器上的數(shù)據(jù)。
3> 創(chuàng)建雙分區(qū)表 使用partition(year string,hour int)
create table tb_stu3(id int,name string) partitioned by (dt string,hour string) row format delimited fields terminated by ',';
加載數(shù)據(jù):load data local inpath '/opt/mysoft/hivedata/student.txt' into table tb_stu3 partition(dt = '20200404',hour='23');
4> 分桶表 (cluster by into num bucked )
? ? 指定開(kāi)啟分桶:set hive.enforce.bucketing = true;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? set mapreduce.job.reduces = 4;
? ? 創(chuàng)建分桶表:
? ? create table tb_stu4(id int,name string) clustered by (id) sorted by(id desc) into 4 buckets row format delimited fields terminated by ',';
? ? 導(dǎo)入數(shù)據(jù)(需要前創(chuàng)建一個(gè)同樣字段的臨時(shí)表,然后導(dǎo)入數(shù)據(jù),再?gòu)呐R時(shí)表中查詢數(shù)據(jù)導(dǎo)入到分桶表):
? ? insert overwrite table tb_stu4 select * from tb_stu cluster by (id)
? ? 分桶表需要使用mr程序進(jìn)行計(jì)算之后再裝載導(dǎo)入到分桶表中,根據(jù)分桶字段的hash值計(jì)算分桶
5> 內(nèi)部表和外部表(EXTERNAL), 主要區(qū)別在于看有沒(méi)有加 external關(guān)鍵字,內(nèi)部表在hive的默認(rèn)路徑下,外部表可以指定目錄,特別是有比較大的數(shù)據(jù)的時(shí)候,不用上傳到hive,直接在hdfs上的文件目錄建立關(guān)聯(lián)。
創(chuàng)建表: create external table tb_stu5(id int,name string) row format delimited fields terminated by ',' location '/input';
外部表當(dāng)元數(shù)據(jù)表刪除的時(shí)候,外部表對(duì)象應(yīng)的數(shù)據(jù)文件不會(huì)被刪除,內(nèi)部表則元數(shù)據(jù)和表文件一塊被刪除。
6> like 語(yǔ)句: 復(fù)制一個(gè)表的表結(jié)構(gòu),但不會(huì)復(fù)制數(shù)據(jù)。
? ? create table stu_like like tb_stu;
7> 修改分區(qū)表:
alter table tb_stu2 partition(age = 20) rename to partition(age=50);
8> hive表的join查詢:
select * from tb_stu t1 join tb_stu2 t2 on t1.id = t2.id where t1.id = 5;
9> 導(dǎo)出數(shù)據(jù):
? ? 導(dǎo)出到本地目錄:
????insert overwrite local directory '/opt/data' select * from tb_stu;
? ? 導(dǎo)出到hdfs目錄:
? ? insert overwrite directory '/input' select * from tb_stu;
10> hive 中創(chuàng)建dual表
? ? ?create table dual(id string);
? ? 在opt/mysoft/hivedata目錄中創(chuàng)建 dual.txt 文件,文件中只保存一個(gè)空格。
? ? 加載數(shù)據(jù)到dual表: load data local inpath '/opt/mysoft/hivedata/dual.txt' into table dual;
? ? 測(cè)試:select substr('hello world',2,3) from dual;
11> 自定義UDF開(kāi)發(fā)函數(shù):
? ? ? hive 可以使用自定義UDF函數(shù)。
? ? 定義步驟:使用maven創(chuàng)建一個(gè)java工程
? ? 1. 導(dǎo)入需要的依賴jar包
? ??????hive-exec-1.2.1.jar和hadoop-common-2.7.4.jar依賴
? ? 2.創(chuàng)建一個(gè)類,繼承org.apache.hadoop.hive.ql.exec.UDF類,重載evaluate()方法,實(shí)現(xiàn)自己的定義方法的業(yè)務(wù)邏輯
? ? 3.打成jar包上傳到服務(wù)器
? ? 4.將jar包添加到hive的classpath
????????hive>addJAR /home/hadoop/udf.jar;
? ? 5. 創(chuàng)建臨時(shí)函數(shù)與開(kāi)發(fā)好的java class關(guān)聯(lián)
? ??????create temporary function tolowercase as 'com.hive.test.udffunc';
? ? ?6.使用自定義函數(shù):select tolowercase('ABCDEF'); 輸出結(jié)果:abcdef
? ??????