安裝
首先說明hive的安裝。
鏈接: http://pan.baidu.com/s/1DleVG 密碼: mej4
這個鏈接是一個視頻的鏈接,視頻中講解了如何安裝hive。
關於視頻中用到的資料文件,我已經上傳到CSDN,請點擊這裏下載。
按照視頻中的講解步驟,完全可以完成hive的安裝和調試。
命令行基本操作
命令行基本操作無非就是增刪改查。
進入hive的命令行模式,命令:hive
建議進入命令行模式使用Hive的安裝目錄下的bin目錄下,因爲可能當運行命令的當前目錄下生成一些日誌文件,時間久了,自己都不知道這些文件是做什麼的了。
命令:show databases;
分號作爲命令行結束符。
命令:use default;
show tables;
創建表,並查詢。
create table ti(id string);
show tables;
select * from ti;
向表中加載數據
load data local inpath ‘/usr/local/id’ into table tb1;
沒有local的話:
load data inpath ‘HDFS文件路徑’ into table [tablename]
,則文件路徑指的是HDFS文件系統
加載數據之後,進行查詢驗證。
刪除表:
drop table tb1;
這幅圖是通過瀏覽器遠程訪問HDFS所看到的Hive管理的數據庫的文件。HIve管理的數據庫是使用HDFS文件系統的方式進行的。所以數據庫的數據都是文件,並可以通過HDFS查看到。圖中看到的就是數據表tb1的數據。
製表符進行分割
CREATE TABLE t2(id int, name string) ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’;
分區表命令
CREATE TABLE t3(id int) PARTITIONED BY (day int);
LOAD DATA LOCAL INPATH ‘/root/id’ INTO TABLE t1 PARTITION (day=22);
桶表命令
create table t4(id int) clustered by(id) into 4 buckets;
set hive.enforce.bucketing = true;
使用桶加載數據 不能使用load data方式加載數據
insert into table t4 select id from t3;
外部表命令
create external table t5(id int) location ‘/external’;
連接查詢
Hive支持連接查詢,但有一些條件必須遵守,比如只支持相等查詢,其它查詢如不等式查詢則不支持,還支持外連接,左半連接查詢。另外Hive支持多於兩個表以上的連接查詢
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
| table_reference CROSS JOIN table_reference [join_condition] (as of Hive 0.10)table_reference:
table_factor
| join_tabletable_factor:
tbl_name [alias]
| table_subquery alias
| ( table_references )join_condition:
ON equality_expression ( AND equality_expression )*equality_expression:
expression = expression
首先是Hive中的連接查詢只支持相等連接而不支持不等連接查詢:
//有效的連接查詢,相等連接查詢
SELECT a.* FROM a JOIN b ON (a.id = b.id AND a.department = b.department)
//無效的連接查詢,Hive不支持不等連接查詢
SELECT a.* FROM a JOIN b ON (a.id <> b.id)
其次是Hive支持兩個表以上的連接查詢:
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
如果所有jion子句都使用了某個表的相同列,Hive將多個表的連接查詢轉換爲一個map/reduce作業。如下所示:
//由於jion子句中使用了表b的key1列,該查詢轉換爲一個作業
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)
//由於表b的key1列用在第一個jion子句中,key2列用在第二個jion子句中,該查詢被轉換爲兩個作業,第一個作業執行表a和b的連接查詢,第二個作業將第一個作業的結果與第二個jion子句進行連接查詢
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
在每個join的map/reduce階段,序列中的最後一個表是以流的方式通過reducers,而其它表則緩存在reducers的內存中。這樣通過將最大的表放在序列的最後有助於減少reducers的內存需求。如:
//下面的查詢中,從a和b中滿足條件的行中提取a.val和b.val,並緩存在reducers的內存中,對於從c中提取的每行記錄,與緩存中的行進行連接計算
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)
//下面的查詢包含兩個作業,第一個作業緩存a的值,將b的值以流的方式通過reducers,第二個作業緩存結果,並將c的值以流的方式通過reducers。
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
在每個join的map/reduce階段,可以通過提示指定要流處理的表:
//下面的查詢中b.val和c.val緩存在reducers的內存中,對於從a中提取的每行記錄,與緩存中的行進行連接計算。如果省略STREAMTABLE提示,jion中最右邊的表被流處理
SELECT /*+ STREAMTABLE(a) */ a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)
LEFT,RIGHT和FULL OUTER,即左連接,右連接和全連接,爲當ON從句不匹配時提供了更多的控制,如:
SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key)
該查詢將返回a中的所有行,當a.key=b.key時返回a.val,b.val,沒有對應的b.key時返回a.val,NULL,b中沒有對應的a.key的行將會丟掉。”FROM a LEFT OUTER JOIN b”必須寫在一行中爲了理解該語句是如何工作的—a在b的左側,a中的所有行被保留。RIGHT OUTER JOIN將保留b中所有的行,FULL OUTER JOIN將保留a中的所有行和b中的所有行。
Join出現在WHERR子句之前。因此如果想限制連接查詢的輸出,限制條件應該出現在WHERE子句中,否則應該出現在JOIN子句中。當在分區表上執行連接查詢時或許會有一些困惑:
//ds爲分區列
SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key)
WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'
當該左外連接在a中發現key而在b中沒有發現key時,b中的列將爲null,包括分區列ds,也就是將會過濾掉連接查詢輸出中沒有有效b.key的列,或者說左外連接與WHERE子句中引用的b中的任何列無關。相反下面的語句將會提前根據條件過濾:
SELECT a.val, b.val FROM a LEFT OUTER JOIN b
ON (a.key=b.key AND b.ds='2009-07-07' AND a.ds='2009-07-07')
Join連接是不可以交換的,無論是LEFT還是RIGHT連接都是左結合的。看下面的示例:
SELECT a.val1, a.val2, b.val, c.val
FROM a
JOIN b ON (a.key = b.key)
LEFT OUTER JOIN c ON (a.key = c.key)
第一個連接a和b,丟掉所有不滿足條件的記錄,結果再與c進行左外連接。如果當key存在於a和c中但不在b中時,結果不是直觀的。A中包含key的行丟棄掉,應爲b中沒有與key對應的行,這樣結果將不包含key,再與c進行左外連接時將不包含c.val,該值將爲null。如果是RIGHT OUTER JOIN的話,結果將爲null,null,null,c.val,分析方法同分析左外連接一樣。
左半連接以高效的方式實現了IN/EXISTS子查詢。左半連接的限制是右側的表只能出現在ON子句中,不能出現在WHERE或者SELECT子句中,如:
SELECT a.key, a.value
FROM a
WHERE a.key in
(SELECT b.key
FROM B);
//兩者是等價的
SELECT a.key, a.val
FROM a LEFT SEMI JOIN b on (a.key = b.key)
如果除了一個表以外的所有正在連接的表都比較小,連接操作可以只作爲map作業執行,如:
SELECT /*+ MAPJOIN(b) */ a.key, a.value
FROM a join b on a.key = b.key
該查詢不需要reducer任務,對於A的每個mapper,B被完全讀取。但a FULL/RIGHT OUTER JOIN b不能被執行。如果正在連接查詢的表在連接列上進行了分桶,並且一個表的桶數是另一個表的桶的倍數,桶可以彼此連接。如果表a有4個桶,b有4個桶,那麼下面的連接查詢可以僅適用mapper任務完成:
SELECT /*+ MAPJOIN(b) */ a.key, a.value
FROM a join b on a.key = b.key
與對於a的每個mapper任務都讀取整個b不同,只讀取被要求的桶。對於上面的查詢,處理a的桶1的mapper任務只讀取b的桶1,但這不是默認行爲,可以使用下面的參數進行配置管理:
hive.optimize.bucketmapjoin = true //默認值爲false
如果表在排序和分桶的列上進行連接查詢,且它們有相同的桶,那麼合併查詢可以被執行。對應的桶在mapper任務中彼此連接,該過程同上。但需要設置下面的參數:
hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;//默認爲org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
hive.optimize.bucketmapjoin = true; //默認值爲false
hive.optimize.bucketmapjoin.sortedmerge = true; //默認值爲false
子查詢語法
SELECT ... FROM (subquery) name ...
Hive只在FROM字句支持子查詢。子查詢必須給一個名字,因爲每個表在FROM字句必須有一個名字。子查詢的查詢列表的列,必須有唯一的名字。子查詢的查詢列表,在外面的查詢是可用的,就像表的列。子查詢也可以一個UNION查詢表達式.Hive支持任意層次的子查詢。
簡單子查詢的例子:
SELECT col FROM (
SELECT a+b AS col FROM t1
) t2
包含UNION ALL的子查詢例子:
SELECT t3.col FROM (
SELECT a+b AS col FROM t1
UNION ALL
SELECT c+d AS col FROM t2
) t3
視圖view
Hive 0.6版本及以上支持視圖
Hive View具有以下特點:
1. View是邏輯存在,Hive暫不支持物化視圖(1.0.3)
2. View只讀,不支持LOAD/INSERT/ALTER。需要改變View定義,可以是用Alter View
3. View內可能包含ORDER BY/LIMIT語句,假如一個針對view的查詢也包含這些語句, 則view中的語句優先級高。例如,定義view數據爲limit 10, 針對view的查詢limit 20,則最多返回10條數據。
4. Hive支持迭代視圖
創建View
CREATE VIEW [IF NOT EXISTS] view_name [(column_name [COMMENT column_comment], ...) ]
[COMMENT view_comment]
[TBLPROPERTIES (property_name = property_value, ...)]
AS SELECT ...
刪除view
DROP VIEW [IF EXISTS] view_name
修改view
ALTER VIEW view_name SET TBLPROPERTIES table_properties
table_properties:
: (property_name = property_value, property_name = property_value, ...)
查詢視圖的定義信息
DESCRIBER EXTENDED viewname
EXPLAIN語法
Hive提供EXPLAIN命令,顯示查詢的執行計劃。語法如下:
EXPLAIN [EXTENDED] query
EXPLAIN語句使用EXTENDED,提供執行計劃關於操作的額外的信息。這是典型的物理信息,如文件名。
Hive查詢被轉換成序列(這是一個有向無環圖)階段。這些階段可能是mapper/reducer階段,或者做metastore或文件系統的操作,如移動和重命名的階段。 EXPLAIN的輸出包括三個部分:
查詢的抽象語法樹
執行計劃計劃的不同階段之間的依賴關係
每個場景的描述
場景的描述,顯示了與元數據相關操作的操作序列。元數據會包括FilterOperator的過濾器表達式,或SelectOperator的查詢表達式,或FileSinkOperator的文件輸出名字。
排序和聚集
//where和having的區別:
//where是先過濾再分組(對原始數據過濾),where限定聚合函數
hive> select count(*),age from tea where id>18 group by age;
//having是先分組再過濾(對每個組進行過濾,having後只能跟select中已有的列)
hive> select age,count(*) c from tea group by age having c>2;
//group by後面沒有的列,select後面也絕不能有(聚合函數除外)
hive> select ip,sum(load) as c from logs groupby ip sort by c desc limit 5;
//distinct關鍵字返回唯一不同的值(返回age和id均不相同的記錄)
hive> select distinct age,id from tea;
//hive只支持Union All,不支持Union
//hive的Union All相對sql有所不同,要求列的數量相同,並且對應的列名也相同,但不要求類的類型相同(可能是存在隱式轉換吧)
select name,age from tea where id<80
union all
select name,age from stu where age>18;
Order By特性:
對數據進行全局排序,只有一個reducer task,效率低下。
與mysql中 order by區別在於:在 strict 模式下,必須指定 limit,否則執行會報錯
使用命令set hive.mapred.mode; 查詢當前模式
使用命令set hive.mapred.mode=strick; 設置當前模式
hive>select*from logs where date='2015-01-02'orderby te;
FAILED: SemanticException 1:52In strict mode,
ifORDERBYis specified, LIMIT must also be specified.
Error encountered near token 'te'
對於分區表,還必須顯示指定分區字段查詢
hive>select*from logs orderby te limit 5;
FAILED: SemanticException [Error 10041]:
No partition predicate found for Alias "logs" Table "logs"
order by 時,desc NULL 值排在首位,ASC時NULL值排在末尾
Sort BY特性:
可以有多個Reduce Task(以DISTRIBUTE BY後字段的個數爲準)。也可以手工指定:set mapred.reduce.tasks=4;
每個Reduce Task 內部數據有序,但全局無序
set mapred.reduce.tasks =2;
insert overwrite local directory '/root/hive/b'select*from logs
sort by te;
上述查詢語句,將結果保存在本地磁盤 /root/hive/b ,此目錄下產生2個結果文件:000000_0 + 000001_0 。每個文件中依據te字段排序。
Distribute by特性:
按照指定的字段對數據進行劃分到不同的輸出 reduce 文件中
distribute by相當於MR 中的paritioner,默認是基於hash 實現的
distribute by通常與Sort by連用
set mapred.reduce.tasks =2;
insert overwrite local directory '/root/hive/b'select*from logs
distribute by date
sort by te;
Cluster By特性:
如果 Sort By 和 Distribute By 中所有的列相同,可以縮寫爲Cluster By以便同時指定兩者所使用的列。
注意被cluster by指定的列只能是降序,不能指定asc和desc。一般用於桶表
set mapred.reduce.tasks =2;
insert overwrite local directory '/root/hive/b'select*from logs
cluster by date;
JAVA API操作Hive數據庫
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class HiveDemo {
public static void main(String[] args) throws Exception {
Class.forName("org.apache.hadoop.hive.jdbc.HiveDriver");
Connection connection = DriverManager.getConnection("jdbc:hive://centos:10000/default", "", "");
Statement stmt = connection.createStatement();
String querySQL="select * from default.tb1";
ResultSet resut = stmt.executeQuery(querySQL);
while (resut.next()) {
System.out.println(resut.getInt(1));
}
}
}
以上代碼就是通過java api操作hive數據庫,獲取數據然後打印。
在運行上面的命令之前,需要在linux系統中啓動hive的遠程服務,命令如下:
hive –service hiveserver >/dev/null 2>/dev/null &
這條命令啓動hive的遠程服務,分毫不差,直接輸入回車就可以了。然後運行上面的java 代碼,運行結果如下:
可以看到結果已經正確打印出來了。
內容引用了網上的比較多的內容。在此感謝衆多同行的付出!如有侵權,請見諒!^_^~~
關於代碼,如果感興趣,請點擊我的github關注整個項目。整個項目中不僅僅本文提到的hive的簡單操作,還有MapReduce,Zookeeper等簡單的應用。歡迎關注。^_^