Hive框架基礎(二)
* Hive框架基礎(二)
我們繼續討論hive框架
* Hive的外部表與內部表
內部表:hive默認創建的是內部表
例如:
create table table001 (name string , age string) location ‘/input/table_data‘;
此時:會在HDFS上新建一個table001表的數據存放地
接著執行:
load data inpath‘/input/data ‘into table table001;(註意,load關鍵字後沒有跟local關鍵字)
** 會將hdfs上的/input/data目錄下的數據轉移到/input/table_data目錄下
** 如果刪除table001表,會將table001表的數據和元數據信息全部刪除,即最後/input/table_data下無數據
** 由於此處load是將HDFS中的數據移到HDFS另一個 目錄,所以,/input/data中的數據已經刪除。
** 如果創建內部表時沒有指定location,就會在/user/Hive/warehouse/下新建一個表目錄
外部表:默認創建的不是外部表,需要使用external關鍵字標識
例如:
create external table etable001(name string, age string);
會在/user/hive/warehouse/新建一個表目錄et
接著執行:
load data inpath ‘/input/edata‘ into table etable001;(註意,load關鍵字後沒有跟local關鍵字)
** 把hdfs上/input/edata/下的數據轉到/user/hive/warehouse/et下
** 刪除這個外部表後,/user/hive/warehouse/et下的數據不會刪除
** 由於此處load是將HDFS中的數據移到HDFS另一個 目錄,所以,/input/data中的數據已經刪除。(和內部表的操作情況一致)
總結:
** 外部表中的數據並不是由它自己來管理,而內部表則不一樣;
** 在刪除內部表的時候,Hive將會把屬於表的元數據和數據全部刪掉;而刪除外部表的時候,Hive僅僅刪除外部表的元數據,數據是不會刪除的。
** 在創建內部表或外部表時加上location的效果是一樣的,只不過表目錄的位置不同而已,加上partition用法也一樣,只不過表目錄下會有分區目錄而已(後續會講到)
** load data local inpath直接把本地文件系統的數據上傳到HDFS上,如果指定了location,則上傳到指定位置,沒有的話上傳到hive默認配置的數據倉庫中。
** 外部表相對來說更加安全,數據組織也更加靈活,方便共享源數據。
* Hive分區表
** 創建表的時候只需要指定分區字段,分區範圍是在加載數據的時候才指定的
** 對大表數據進行分類存儲,提高數據安全性
** 使用分區表能大大的提高查詢效率
** 創建分區表
此部分直接舉例說明,講解這部分知識涉及到的例子所需要用到的數據材料請到傳送門下載:
鏈接:http://pan.baidu.com/s/1dFCFuSD 密碼:fc41
create database if not exists db_web_data ;
create table if not exists db_web_data.track_log(
id string,
url string,
referer string,
keyword string,
type string,
guid string,
pageId string,
moduleId string,
linkId string,
attachedInfo string,
sessionId string,
trackerU string,
trackerType string,
ip string,
trackerSrc string,
cookie string,
orderCode string,
trackTime string,
endUserId string,
firstLink string,
sessionViewNo string,
productId string,
curMerchantId string,
provinceId string,
cityId string,
fee string,
edmActivity string,
edmEmail string,
edmJobId string,
ieVersion string,
platform string,
internalKeyword string,
resultSum string,
currentPage string,
linkPosition string,
buttonPosition string
)
partitioned by (date string,hour string)
row format delimited fields terminated by ‘\t‘;
字段設計緣由請參看字典:
將以上文本包含的sql命令保存到p2.hql文件中,然後使用命令:
$ bin/hive -f hqlDir/p2.hql,如圖:
這裏我把hql文件歸類到了自己創建的hqlDir文件夾中** 加載數據
首先將“2015082818”和“2015082819”兩個文件考入到/home/z/Desktop目錄下
使用命令:
hive (default)> load data local inpath ‘/home/z/Desktop/2015082818‘ into table db_web_data.track_log partition(date=‘20150828‘,hour=‘18‘);
hive (default)> load data local inpath ‘/home/z/Desktop/2015082819‘ into table db_web_data.track_log partition(date=‘20150828‘,hour=‘19‘);
** 查詢數據
hive (default)> select * from db_web_data.track_log where date=‘20150828‘ ;
hive (default)> select * from db_web_data.track_log where date=‘20150828‘ and hour=‘18‘;
(這裏由於數據量太大,就不給大家截圖展示了)
拓展:
查看一個分區表有幾個分區
hive (db_web_data)> show partitions track_log ;
刪除一個分區表的分區
hive (db_web_data)> alter table track_log drop partition(date=‘xxxx‘,hour=‘xxxx‘) ;
* Hive創建表的方式
** 方案一
即創建一個空表,例如之前我們一直用到的方式。
** 方案二
即把一張表的某些字段抽取出來,創建成一張新表
例如:
create table db_web_data.backup_track_log as select * from db_web_data.track_log;
** 方案三
復制表結構
尖叫提示:以上創建表的過程均可以使用location指定創建位置,也可以不指定。
例如:
create table db_web_data.like_track_log like db_web_data.track_log;
* Hive表導入數據方式
** 方案一
加載本地文件到Hive表
load data local inpath ‘path/file‘ into table 表名稱 ;
** 方案二
加載HDFS文件到HIVE表(即方案2沒有local關鍵字)
load data inpath ‘path/file‘ into table 表名稱 ;
** 方案三
加載數據覆蓋表中已有的數據
load data local inpath ‘path/file‘ overwrite into table 表名稱 ;
** 方案四
創建表時通過select加載
create table db_web_data.track_log_as as select * from db_web_data.track_log;
** 方案五
用insert命令加載
*** 應用場景:把用select命令分析的結果寫入某個臨時表
*** append 追加寫入 --默認
*** overwrite 覆蓋寫入 --使用最多
--先要創建好表,然後再寫入數據
insert into table 表名 select * from db_web_data.track_log;
insert overwrite table 表名 select * from db_web_data.track_log;
* Hive表導出數據方式
** 方案一
insert...local diretory導出到本地
例如:
insert overwrite local directory "/home/z/Desktop/backup" row format delimited fields terminated by ‘\t‘ select * from staff ;
** 方案二
insert..diretory導出到HDFS
例如:
insert overwrite diretory "path/" select * from staff;
** 方案三
直接在linux段,使用hive -e命令執行hql語句
例如:
$ bin/hive -e "select * from staff;" > /home/z/backup.log
** 方案四
sqoop工具(後面討論)
* Hive語句基本拓展
** 查詢具體的某個某些字段
例如:
select name, sex from staff;
** where
select * from staff where name=‘隔壁老王‘;
註:where 條件可以是分區字段
** limit
select * from track_log limit 1 ;
** distinct 去重
select distinct(name) from staff ;
** < > = >= <= !=
select * from staff where id > 5000 ;
** and 、between ... and ... 、 not in 、in
** like % _
** + - * /
以上各種運用詳細可以參考sql語法
* Hive 常用函數
** 查看有哪些函數
hive (default)> show functions;
** 查看具體某個函數的用法
hive (default)> desc function extended max ;
** 常用函數一些用法
假設情景:我們有如下兩個表,分別是員工信息表emp和部門信息表dept,表內容如下圖:
emp:
字段:empno int, ename string, job string, mgr int, hiredate string, sal double, comm double, deptno int
字段對應數據:
dept:
字段:deptno int, dname string, loc string
字段對應數據:
請自行創建數據庫:
db_emp_dept
以及對應表:
emp、dept
並導入數據
鏈接:http://pan.baidu.com/s/1qY8pjTq 密碼:54w6
最終如圖:
以上面的情景,解釋下面的函數:
*** 最大值統計函數: max
語法: max(col)
返回值: double
說明:統計結果集中col字段的最大值
例如:顯示每個部門最高薪資
select deptno,max(sal) from emp group by deptno ;
結果如圖:
例如:顯示部門名稱, 部門最高薪資
select max(b.dname),max(sal) from emp a inner join dept b on a.deptno = b.deptno group by a.deptno ;
結果如圖:
或者:select b.dname,max(sal) from emp a inner join dept b on a.deptno = b.deptno group by a.deptno,dname ;
結果如圖:
*** 最小值統計函數: min
語法:min(col)
返回值::double
說明:統計結果集中col字段的最小值
例如:顯示部門名稱, 部門最高薪資, 部門所在的城市
select max(dname),max(sal),min(loc) from emp inner join dept on emp.deptno = dept.deptno group by emp.deptno ;
結果如圖:
*** 平均值統計函數: avg
語法: avg(col), avg(DISTINCT col)
返回值: double
說明: avg(col)統計結果集中col的平均值;avg(DISTINCT col)統計結果中col不同值相加的平均值
例如:請參照前文內容,自行測試
*** 總和統計函數: sum
語法: sum(col), sum(DISTINCT col)
返回值: double
說明: sum(col)統計結果集中col的相加的結果;sum(DISTINCT col)統計結果中col不同值相加的結果
例如:請參照前文內容,自行測試
*** 個數統計函數: count
語法: count(*), count(expr), count(DISTINCT expr[, expr_.])
返回值: int
說明: count(*)統計檢索出的行的個數,包括NULL值的行;count(expr)返回指定字段的非空值的個數;count(DISTINCTexpr[, expr_.])返回指定字段的不同的非空值的個數
例如:請參照前文內容,自行測試
*** 取隨機數函數: rand
語法: rand(),rand(int seed)
返回值: double
說明:返回一個0到1範圍內的隨機數。如果指定種子seed,則會等到一個穩定的隨機數序列
例如:select rand();
*** 字符串連接函數:concat
語法: concat(string A, string B…)
返回值: string
說明:返回輸入字符串連接後的結果,支持任意個輸入字符串
例如:select concat(empno,"_",ename) from emp ;
結果如圖:
*** 字符串截取函數:substr
語法: substr(string A, int start, int end)
返回值: string
說明:返回字符串A從start位置到結尾end的字符串,end不填寫,則默認為末尾。
例如:select substr(hiredate,1,4) from emp ;(請自行去掉4,再試一次,即可明白)
結果如圖:
*** 字符串轉大寫函數:upper
語法: upper(string A)
返回值: string
說明:返回字符串A的大寫格式
*** 字符串轉小寫函數:lower
語法: lower(string A)
返回值: string
說明:返回字符串A的小寫格式
*** 日期轉天函數: day
語法: day (string date)
返回值: int
說明:返回日期中的天。
例如:select day(hiredate) from emp ;
結果如圖:
*** 日期轉小時函數: hour
語法: hour (string date)
返回值: int
說明:返回日期中的小時。
例如:select hour("2016-09-01 12:34:34") ;
*** 日期轉分鐘函數: minute
語法: minute (string date)
返回值: int
說明:返回日期中的分鐘。
*** 日期轉秒函數: second
語法: second (string date)
返回值: int
說明:返回日期中的秒。
*** 日期轉UNIX時間戳函數:unix_timestamp
語法: unix_timestamp(string date)
返回值: bigint
說明:轉換格式為"yyyy-MM-ddHH:mm:ss"的日期到UNIX時間戳。如果轉化失敗,則返回0。
舉例:
select unix_timestamp("2018-07-07 12:34:34") ;
select unix_timestamp(‘2011-12-07 13:01:03‘) from table;
*** UNIX時間戳轉日期函數:from_unixtime
語法: from_unixtime(bigint unixtime[, string format])
返回值: string
說明:轉化UNIX時間戳(從1970-01-01 00:00:00 UTC到指定時間的秒數)到當前時區的時間格式
例如:
select from_unixtime(1472704474) ;
select from_unixtime(1472704474,‘yyyyMMdd‘) from table;
*** 類型轉換函數:cast
類型轉換函數: cast
語法: cast(expr as )
返回值: Expected "=" to follow "type"
說明:返回array類型的長度
例如:select cast(1472704474123/1000 as int) ;
*** 條件判斷函數:CASE
語法: CASE WHEN a THEN b [WHEN c THEN d]* [ELSE e] END
返回值: T
說明:如果a為TRUE,則返回b;如果c為TRUE,則返回d;否則返回e
例如:
> select ename,sal+comm from emp ;
hive (db_emp_dept)> select ename,
> case when comm is null then 0+sal
> else comm+sal end
> from emp ;
hive (db_emp_dept)> select ename,
> case when sal<1000 then "lower"
> when sal>=1000 and sal<=2000 then "pass"
> when sal>2000 then "high"
> else "OK" end
> from emp ;
hive (db_emp_dept)> select ename,
> case when sal<1000 then deptno
> when sal>=1000 and sal<=2000 then comm
> else null end
> from emp ;
對於語法不了解的,請移步:SQL基礎
* Hive explain 解析執行計劃
hive是把sql語句翻譯成mapreduce任務來執行的,那麽具體mapreduce是怎麽一個執行結構,可以在sql前面加上explain關鍵字來查看。
例如:
explain select count(distinct(deptno)) from emp ;
* Hive 設定哪些語句執行mapreduce運算
參數名:hive.fetch.task.conversion
參數值:minimal或者more
從Hive 0.10.0版本開始,對於簡單的不需要聚合的語句,比如select <clo> from <table> limit n這樣的語句,根本不需要啟動mapreduce job,直接通過fetch task即可獲取數據,那麽此時,我們就配置這個屬性的值為more即可。可以查看對應的官方解釋如下:
配置後如圖:
* 配置HiveServer2服務
啟動Hive有如下幾種方式:
1、 hive 命令行模式
進入hive安裝目錄,輸入bin/hive的執行程序,或者輸入 hive –service cli
用於linux平臺命令行查詢,查詢語句基本跟sql查詢語句類似
2、hive web界面的啟動方式,沒什麽用
3、hive 遠程服務 (端口號10000) 啟動方式
bin/hive –service hiveserver2
用java,python等程序實現通過jdbc等驅動的訪問hive。
** 配置hive-site.xml
屬性:hive.server2.thrift.port,值:10000
屬性:hive.server2.thrift.bind.host,值:z01
屬性:hive.server2.long.polling.timeout,值:5000(註意,此處去掉默認帶有的L)
此處就不再配圖了。
** 檢查端口
首先,檢查10000端口是否被占用:
$ netstat -antp|grep 10000
如果被占用,使用kill -9 <pid>殺掉
** 啟動服務
$ bin/hive --service hiveserver2
註意:service前面有兩個“-”
** 連接服務
$ bin/beeline
beeline> help
> !connect jdbc:hive2://z01:10000
(註意:此處如果直接敲回車,不使用用戶登錄,那麽默認為匿名登錄,用戶名為:anonymous,無密碼)
(註意:在我這裏,我也可以使用z這個用戶名登錄,密碼是我自己的密碼)
> select * from db_emp_dept.emp ;
如圖:
註意,如果需要執行Job任務,則:
首先修改該屬性
hive.server2.enable.doAs:false
解釋:改屬性為true時,啟動hiveServer2的用戶為當前默認用戶,訪問Hadoop則也用該用戶。
如果為false,則beeline中登錄的是哪個用戶,就用哪個用戶,這裏我的環境中,可以使用“z”這個用戶。
這樣一來,才能成功在hiveServer2中提交並運行Job任務。
* UDF
即:user defined function
UDF函數開發要點:
** 必須繼承UDF類
** 重寫evaluate函數
** 必須要有返回類型,可以返回null,但是返回類型不能為void
** 建議使用Text/LongWritable
** 環境配置
1、在eclipse中創建一個maven項目,並修改pom依賴包,添加如圖所示內容:
2、上傳repository.tar.gz,並解壓到/home/z/.m2/
3、修改maven的配置文件
$ vi /opt/modules/apache-maven-3.0.5/conf/settings.xml
在mirrors標簽中加入如下內容:
接著,將該文件拷貝到.m2目錄下:
$ cp settings.xml /home/z/.m2/
4、更新maven工程
在eclipse中右鍵項目,選擇maven-update project即可。
** 編寫並使用UDF
*** 例如我們編寫一個UDF函數,用來將制定字段內容轉換為小寫:
*** 將程序打成jar包後,導入該jar
hive (default)> add jar /home/z/Desktop/lower.jar;
*** 創建臨時函數:
hive (default)> create temporary function my_lower as ‘com.z.demo.udf.Lower‘;
*** 使用該函數
hive (default)> show fuctions ;
hive (default)> select my_lower(ename) from db_emp_dept.emp;
*** 註意事項:
**** 以上方式添加的UDF函數是臨時生效的,只要退出當前hive窗口,便失效,一般不會設置永久生效。
**** 實際應用中,Hive會有多個Job任務,每個job任務都有自己對應的函數、以及hql語句; 每個job任務增加函數的語句和具體的業務分析語句一般會把它放到一個文件中(比如:job01.hql、job02.hql、job03.hql),然後使用bin/hive -f job1.hql方式執行即可。
* 自動化腳本-加載本地目錄的指定數據到HDFS
腳本如下:
對應的auto.hql文件中的內容如下:
* 總結
本節主要講解hive的一些高級用法,以及如何開發自定義函數用使用。
個人微博:http://weibo.com/seal13
QQ大數據技術交流群(廣告勿入):476966007
作者:Z盡際
鏈接:https://www.jianshu.com/p/4c105383b959
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請註明出處。
Hive框架基礎(二)