目錄
2、Hive錶行轉列,列轉行以及Hive Lateral View在列轉行中的使用
一、Hive Lateral View
1、基本介紹
Lateral View用於和UDTF函數(explode、split)結合來使用。 首先通過UDTF函數拆分成多行,再將多行結果組合成一個支持別名的虛擬表。主要解決在select使用UDTF做查詢過程中,查詢只能包含單個UDTF,不能包含其他字段、以及多個UDTF的問題。
語法:
LATERAL VIEW udtf(expression) tableAlias AS columnAlias (',' columnAlias)
2、Hive錶行轉列,列轉行以及Hive Lateral View在列轉行中的使用
- 表1:cityInfo
cityname |
regionname |
上海 |
四川北路 |
上海 |
虹梅路 |
上海 |
音樂學院 |
上海 |
徐家彙 |
上海 |
陸家嘴 |
上海 |
古北 |
北京 |
東四 |
北京 |
復興門 |
北京 |
新街口 |
北京 |
地安門 |
- 表2:cityInfoSet
cityname |
regionname |
上海 |
四川北路,虹梅路,音樂學院,徐家彙,陸家嘴,古北 |
北京 |
地安門,復興門,東四,新街口 |
表1和表2的結構如上所示。
現在需要在 hive 中使用 Hql 語句對錶1和表2進行互相轉化。
(1)行轉列
使用的函數說明:
concat_ws(string SEP,string array<String>):函數返回字符串連接後的結果,SEP表示各個字符串連接的分割符;
collect_set(col): 函數將col字段進行去重,併合併成一個數組。
表1=>表2 可以使用 hive 的內置函數 concat_ws() 和 collect_set()進行轉換,執行代碼如下所示:
select cityname,concat_ws(',',collect_set(regionname)) as address_set from cityInfo group by cityname;
(2)列轉行
使用到的函數
函數split(String str,String pat) 將字符串按照pat分割;
函數explode(array) 將數組中的元素拆分爲多行顯示。
表2=>表1 可以使用 hive 的內置函數 lateral view explode()進行轉化。代碼如下:
select cityname, regionname from cityInfoSet lateral view explode(split(address_set, ',')) aa as region;
二、Hive視圖
1、Hive視圖基本介紹
視圖是一個虛擬表,其內容由查詢定義。Hive 中的視圖和RDBMS中視圖的概念一致,都是一組數據的邏輯表示,本質上就是一條SELECT語句的結果集。視圖是純粹的邏輯對象,沒有關聯的存儲(Hive 3.0.0引入的物化視圖除外),當查詢引用視圖時,Hive可以將視圖的定義與查詢結合起來,例如將查詢中的過濾器推送到視圖中。
2、Hive視圖特點
(1)不支持物化視圖 ;
(2)只能查詢,不能做加載數據操作 ;
(3)視圖的創建,只是保存一份元數據,查詢視圖時才執行對應的子查詢 ;
(4)view定義中若包含了ORDER BY/LIMIT語句,當查詢視圖時也進行了ORDER BY/LIMIT語句操作,view當中定義的優先級更高 ;
(5)Hive視圖支持迭代視圖。
3、Hive視圖的意義
(1) 使用視圖使數據操作更簡便,相當於封裝了sql語句,類似於關係型數據庫中的存儲過程。
(2) 使用視圖,基表中的數據有了一定的安全性,使用視圖可以基於限制條件過濾數據,通過視圖限制數據訪問可以保護信息不被隨意查詢。
4、Hive視圖的創建和刪除
--創建視圖:
CREATE VIEW [IF NOT EXISTS] [db_name.]view_name
[(column_name [COMMENT column_comment], ...) ]
[COMMENT view_comment]
[TBLPROPERTIES (property_name = property_value, ...)]
AS SELECT ... ;
--查詢視圖:
select colums from view;
--刪除視圖:
DROP VIEW [IF EXISTS] [db_name.]view_name;
案例:
CREATE VIEW gal_view IF NOT EXISTS AS SELECT * FROM product1 p LEFT JOIN logistic l ON p.sku=l.lsku;
5、視圖的使用
SELECT sku,price FROM gal_view;
6、查詢所有的hive視圖
(1) show tables可以查看到新增的視圖
查看結構 :
(2) Hive的元數據信息一般存儲在mysql,Hive的視圖信息存儲在mysql hive數據庫中的 TBLS 表中,通過如下查詢語句可以查詢得到Hive中的所有視圖:
SELECT * FROM TBLS WHERE TBL_TYPE='VIRTUAL_VIEW';
結果:
三、Hive索引
hive的索引可以提高數據的檢索效率,避免全表掃描和資源浪費,對於含有group by的語句,對group by的字段添加索引可以提高查詢速度。
1、Hive索引的實現原理
在指定列上建立索引,會產生一張索引表(Hive的一張物理表),裏面的字段包括,索引列的值、該值對應的HDFS文件路徑、該值在文件中的偏移量。
在執行索引字段查詢時候,首先額外生成一個MR job,根據對索引列的過濾條件,從索引表中過濾出索引列的值對應的hdfs文件路徑及偏移量,輸出到hdfs上的一個文件中,然後根據這些文件中的hdfs路徑和偏移量,篩選原始input文件,生成新的split,作爲整個job的split,這樣就達到不用全表掃描的目的。
2、創建索引
創建索引的字段最好使用不更新的字段,以免頻繁重建索引數據。每次建立、更新數據後,都要重建索引以構建索引表。
現在有一張表名爲product1的表,需要將該表中的sku字段建立一個索引,案例:
create index test_index on table product1(sku)
as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'
with deferred rebuild
in table product1_index;
create index test_index2 on table product1(sku) as 'bitmap' with deferred rebuild in table product1_index2;
兩種創建方式 as 後表示兩種不同的索引處理器。
創建示例如下(這裏採用的bitmap索引處理器):
0: jdbc:hive2://cdh-001:10000/test> show tables;
+-----------+--+
| tab_name |
+-----------+--+
| gal_view |
| logistic |
| product1 |
| stocks |
+-----------+--+
4 rows selected (0.027 seconds)
//創建索引
0: jdbc:hive2://cdh-001:10000/test> create index test_index2 on table product1(sku) as 'bitmap' with deferred rebuild in table product1_index2;
0: jdbc:hive2://cdh-001:10000/test> show tables;
+------------------+--+
| tab_name |
+------------------+--+
| gal_view | //這是之前創建的視圖
| logistic |
| product1 |
| product1_index2 | //可以看到這裏多了一張索引表
| stocks |
+------------------+--+
5 rows selected (0.033 seconds)
//重建索引生成索引數據(建立索引之後必須重建索引才能生效)
0: jdbc:hive2://cdh-001:10000/test> alter index test_index2 on product1 rebuild;
//創建完成後通過索引命令顯示索引
0: jdbc:hive2://cdh-001:10000/test> SHOW FORMATTED INDEX ON product1;
+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+--+
| idx_name | tab_name | col_names | idx_tab_name | idx_type | comment |
+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+--+
| idx_name | tab_name | col_names | idx_tab_name | idx_type | comment |
| | NULL | NULL | NULL | NULL | NULL |
| | NULL | NULL | NULL | NULL | NULL |
| test_index2 | product1 | sku | product1_index2 | bitmap | |
+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+--+
3、使用索引
hive默認不使用索引,需要設置才能使索引生效:
SET hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;
SET hive.optimize.index.filter=true;
SET hive.optimize.index.filter.compact.minsize=0;
//執行查詢
select * from product1 where sku=272480720;
4、刪除索引
DROP INDEX IF EXISTS product1_index2 ON product1;
5、放棄索引
說了這麼多,但是我一般不使用索引,因爲在使用的過程中總是會出現很多奇怪的問題,就很煩,例如刪除索引時,經常出現執行成功,但是索引並沒有被刪除的情況,只有刪除原始數據表(案例中的product1),這個索引纔會被刪除,這在生產上一般是不被允許的。
但是對於數據量很大的表之間的關聯,對關聯字段建立索引還是有必要的,能夠較大程度上提高查詢速度,需要根據自身的業務和需求來確定是否使用索引。