1. 程式人生 > 實用技巧 >3. Hive相關知識點

3. Hive相關知識點

以下是閱讀《Hive程式設計指南》後整理的一些零散知識點:

1. 有時候使用者需要頻繁執行一些命令,例如設定系統屬性,或增加對於Hadoop的分散式記憶體,加入自定的Hive擴充套件的Jave包(JAR檔案),我們可以將這些命令加入hiverc檔案裡,這樣每當CLI(command-line interface命令列介面)啟動時,在‘hive>’提示符出現前先執行這個hiverc檔案

2. Hive指令碼(.hql字尾檔案)註釋--

3.在Hive內使用Hadoop的dfs命令,直接在Hive CLI中執行Hadoop的dfs命令就行了,而且更高效,因為Hadoop每次都會啟動一個新的JVM例項,而Hive會在同一個程序中執行這些命令。

dfs -ls / ;

4.1位元組=8位(1 byte = 8bit);1字=2位元組(1 word = 2 byte);1數字=1位元組。

5.Hive的集合資料型別有struct(類似類的物件,欄位名.first), map(字典, 欄位名['last']), array(陣列,陣列名[1])。

6. Hive的優點:容錯率和糾錯率高能有效避免表命令衝突,能避免誤刪

  (1)容錯率和糾錯率高:傳統資料庫是寫時模式(schema on write),即資料在寫入資料庫時對模型進行檢查。Hive是讀時模式(schema on read),即資料檢查時發生在查詢時。Hive如果在讀完去時發現非數值型的字串的話,對於那些欄位會返回null值,儘可能進行糾錯。

  (2) 能有效避免表命令衝突:Hive中資料庫的概念本質上僅僅是表的一個目錄或者名稱空間,這樣可以避免表命名衝突。

  (3) 能避免誤刪:Hive不允許使用者刪除一個包含有表的資料庫的,使用者要麼先刪除資料庫中的表,然後再刪除資料庫。要麼再刪除命令的最後加上關鍵詞CASCADE(drop database if exists table_name cascade;),這樣可以使Hive自行先刪除資料中的表。此外,資料庫的元資料不可更改(包括庫名和庫的目錄位置),只能修改資料庫的鍵值對屬性值(不是表相關的屬性,而是資料庫的屬性)。

7. 管理表(即內部表)和外部表:Hive建立的表分為管理表(也稱內部表),還有外部表。Hive讓外部表不具有對資料的所有權,因此刪除外部表不會刪除這份資料,只是刪除了外部表描述表的的元資料資訊。使用describe extended tablename;

。可以檢視tableType,若MANGAGED_TABLE,則是管理表,若EXTERNAL_TABLE,則是外部表。

8. 效能調優:聚合效能,JOIN優化(表連線順序安排),JOIN優化(map-side JOIN),並行執行

  (1) 聚合效能調優:set hive.map.aggr=true;提高聚合(例如sum,count, avg等)的效能,這個設定會出發map階段進行頂級聚合過程,非頂級的聚合過程將會在執行一個group by後進行,不過,這個設定將需要更多的記憶體。

  (2) JOIN優化(表連線順序安排):Hive假定查詢中最後一個表是最大的那個表,在對每行記錄進行連線操作時,它會嘗試將其它表快取起來,然後掃描最後那個表進行計算。因此,使用者需要保證連線操作中的表的大小從左到右時依次增加的。簡單來說,join的順序應該時從小到大的表連線。使用/*STREAMTABLE*/在表名前可以提供標記機制來顯示地告之查詢優化器哪張表的大表。

  (3)JOIN優化(map-side JOIN):所有所有表中只有一張表是小表,那麼可以在最大的表通過mapper的時候將小表完全放到記憶體中,Hive可以在map端執行連線過程(稱為map-side JOIN),這是因為Hive可以和記憶體中的小表進行逐一匹配,從而省略掉常規連線操作所需要的reduce過程。即使對於很小的資料集,這個優化也明顯地要快於常規的連線操作。其不僅減少了reduce過程,而且有時還可以統計減少map過程的執行步驟。可通過直接開啟的配置引數set hive.auto.convert.join=true;讓JOIN時自動判定大小表去進行優化。另外,Hive預設判定大小的大小閾值時25MB,你也可以進行改動:hive.mapjoin.smalltable.filesize=25000000;。需要注意的是Hive對於right outer join和full outer join不支援這個優化。

  (4) 並行執行:Hive中某個特定的job可能包含眾多階段且非完全互相依賴的,這樣是可以設定set hive.exec.parallel = true;開啟並行執行job中的階段,利用好叢集。

9.不能在where語句中使用列別名。

10.儘量避免使用float,因為float和double有時候在對比時會出問題,例如0.2的float值是0.200000100000,而0.2的double值是0.200000000001。可以用cast轉化為浮點值例如:cast(0.2 as float)。對浮點數進行比較時,需要保持極端謹慎的態度,要避免任何從窄型別隱式轉換到更廣泛型別的操作。

11.Hive的嚴格模型set hive.mapred.mode = strict;可以禁止3種類型的查詢:

  (1) 對於分割槽表,除非where語句中含有分割槽欄位過濾條件來限制資料範圍,否則不允許執行,就是不允許掃描所有分割槽,取數會快些。
  (2) 因為order by為了執行排序會將所有的結果資料分發到同一個reducer中進行處理,嚴格模式強制要求使用者增加這個limit語句可以防止reducer額外執行很長一段時間。
  (3) 限制笛卡爾積的查詢,可以高效地將where語句轉化成on語句。

12.Hive是按照輸入的資料量大小來確定reducer個數,可以通過dfs -count;命令來計算輸入量大小。

13.Hadoop的job是I/O密集型而不是CPU密集型,壓縮可以提高效能,但如果使用者job是CPU密集型的話,使用壓縮可能會降低執行效能。使用壓縮的優勢是可以最小化做需要的磁碟儲存空間,以及減小磁碟和網路I/O操作。不過檔案壓縮過程和解壓縮過程會增加CPU開銷

14.雖然壓縮檔案確實能夠節約儲存空間,但是在Hadoop中儲存裸壓縮檔案的一個缺點是,通常這些檔案是不可分割的,可分隔的檔案可以劃分成多個部分,由多個mapper並行進行處理。大多數的壓縮檔案是不可分割的,只能從頭讀到尾

15. Hadoop儲存格式:

  (1) SequenceFile:其檔案是含有鍵-值對的二進位制檔案,當Hive將查詢轉換成MapReduce job時,對於指定的記錄,其取決使用哪些合適的鍵值對。它適用於在Hive和其他Hadoop相關的工具中共享檔案,而不適用Hadoop生態系統之外的其它工具。Hadoop的sequence file儲存格式可以將一個檔案劃分成多個塊,然後採用一種可分割的方式對塊進行壓縮。如果想在Hive中使用sequence file儲存格式,可以進行下列指定create table a_sequence_file_table storted as sequencefile;。sequence file由三種壓縮方式:None,record(預設,記錄級別),block(塊級別,壓縮效能最好而且可分割)。

  (2) HAR:Hadoop有一種儲存格式名為HAR,就是Hadoop Archive歸檔檔案,一個HAR檔案就像在HDFS檔案系統中一個TAR檔案一樣是一個單獨的檔案,不過其內部可以存放多個檔案和資料夾。如果某個特定分割槽下儲存的檔案有成千上萬且被訪問的概率要低很多的話,那麼就需要HDFS中的NameNode消耗非常大的代價來管理這些檔案,通過將分割槽下的檔案歸檔成一個巨大的,但同時可以被Hive訪問的檔案,可以減輕NameNode的壓力。不過缺點是HAR檔案查詢效率不高且不屬於壓縮,不會節約儲存空間。例如:alter table ...archive partition語句將錶轉化成一個歸檔表,用alter table ... unarchive partition可以將HAR中檔案提取出來,然後放置到HDFS中。

  (3) RCfile:因為大多數表具有的欄位個數都不大,所以大多數Hadoop和Hive儲存時行式儲存,按塊壓縮起來處理重複資料比較高效。但有時候查詢只需要其中一小部分欄位,這時掃描所有行而過濾掉大部分資料顯然是個浪費,這時採用RCfile進行列式儲存會更利於工作。展示rcfile檔案內容可以通過rcfilecat工具實現(bin/hive --service rcfilecat RCFile檔案路徑)。

16. 加入UDF使用者自定義函式的方法:

  (1) 臨時加入:將程式碼打包成JAR檔案,使用ADD JAR和CREATE TEMPORARY FUNCTION。
  (2) 永久加入:對於Hive原始碼得對functionregistry類進行程式碼修改,然後按照Hive原始碼分支的編譯方式對Hive原始碼重新編譯即可。

17. 函式類方法:UDF、巨集命令和Streaming

  (1) UDF:Java編寫,UDF是指使用者自定義函式。可用於返回array陣列和structure結構體,但是它們無法返回多列或多行。UDTF使用者自定義表生成函式可以返回多列或多行,其使用的類繼承自GenericUDTF介面。

  (2)巨集命令提供了在HiveQL中呼叫其它函式的操作符來定義函式的功能,對於特定的情況,使用巨集命令比Java編寫UDF或使用Hive的streaming功能更加方便,因為巨集命令無需額外編寫程式碼或指令碼,可以使用create temporary macro語法來建立sigmoid函式:

create temporary macro sigmoid (x double) 1.0 / (1.0 + exp(-x));
select sigmoid(2) from src limit 1;

  (3)Streaming:它是Hadoop裡的一個API,它的執行效率通常會比UDF或改寫InputFormat物件的方式要低,但可以不用寫Java程式碼。Hive提供了多個語法使用streaming,包括map(),reduce()和transform(),通常建議使用常規的transform()語句。streaming可以用unix系統或其衍生系統自帶的如cat和sed這樣的系統指令碼程式處理資料,如下:

select transform (col1, col2)
using '/bin/cat' as (newA int, newB double) from a;

streaming也可以用add file功能將bash shell檔案(也能用perl指令碼)加入分散式快取中,新增檔案會被儲存到每個task節點機器的當前工作目錄下,這樣就能直接用transform task而不用去找檔案在哪了:

add file ${env:HOME}/prog_hive/ctof.sh;
select transform(col1) using 'ctof.sh' as convert from a;

18.SerDe是序列化/反序列化的簡寫形式。

19.XPATH是XML的路徑語言。例如:

hive>select xpath (\'<a><b id="foo">b1</b><b id="bar">b2</b></a>',\'//@id\')
from src limit 1;
>>[foo", "bar]

20.如果想要通過程式設計的方式遠端訪問Hive,可以考慮使用HiveServer或者HiveThrift,其允許通過指定埠訪問Hive。

21. Hive中的許可權管理:

當屬性hive.metastore.authorization.storage.checks的值為true時,如果使用者沒有許可權刪除表底層的檔案,Hive就會阻止使用者來來刪除這樣的表。這個引數的預設值時False,而其應該是設定為true的。當在安全模式下執行時,Hive元資料儲存要儘可能將hive.metastore.execute.setugi設定為true。

Hive預設情況下,授權模組時不開啟的,如果要開啟授權,得set hive.security.authorization.enabled=true;

開啟授權後便可以對使用者(user)、組(group)或者角色(role)授予許可權或者回收許可權。

  (1)使用者授權:例如:

先檢視Hive中的使用者的系統使用者名稱
hive> set system:user.name;
system:user.name=edward

# 給該使用者授予建表許可權
hive>grant create on database default to user edward;

# 此時該使用者便具有的建表許可權
hive>create table authorization_test(key int, value string);

# 通過show grant命令檢視授權結果
hive> show grant user edward on database default;

  (2)組授權:當用戶很多同時表也很多的情況下,基於使用者級別的許可權授予會帶來高成本的運維成本。更好的選擇是基於組(group)級別的許可權授予。例如將edward加入某表的選擇許可權裡的組裡:

hive>grant select on table authorization_test_group to group edward;

  (3)角色授權:如果使用者user和組group仍不夠靈活的化,可以用角色role,使用者可以放置在角色中同時可以為角色進行授權,角色比較靈活,因為和組不一樣,組是由系統外部進行控制的,而角色是由Hive內部進行控制的。如果現在建表可以,但選擇表報無許可權錯誤,可以如下角色授權:

# 建立角色存放的地方
hive>create role users_who_can_select_authentication_test_role;
# 把edward使用者放入角色存放點裡 hive
>grant role users_who_can_select_authentication_test_role to user edward;
# 把給定的表授權進行選擇,授權的目標使用者都是給定的角色集裡的使用者 hive
>grant select on table authentication_test_role to role users_who_can_select_authentication_test_role;
# 現在使用者就有選擇許可權了 hive
>select * from authentication_test_role;

針對表,我們有授予全部許可權和授予分割槽許可權兩種授予方式:

  (1) 全部許可權授予:hive>grant all on table a_part_table to user edward;

  (2) 分割槽許可權授予:只需要將表屬性partition_level_privilege為true就行了

# 給分割槽許可權前得給alter許可權
hive>grant alter on table authorization_part to user edward;

# 給分割槽許可權
hive>alter table authorization_part set tblproperties("partition_level_privilege"="true");

# 現在有許可權操作表的分割槽了
hive>alter table authorization_part add partition(ds='3');

# 撤銷使用者在表內某分割槽內容的選擇許可權
hive>revoke select on table authorization_part partition(ds='3') from user edward;

自動授權:設定hive.security.authorization.createtable.owner.grants為建立表的使用者自動授予對這張表的指定的許可權(對建立表的select和drop許可權)。也可以為組或角色設定自動授權,例如hive.security.authorization.creatable.group.grantshivehive.security.authorization.creatable.role.grants

22.Hive中包含了一個使用Apache Zookeeper進行鎖定表的功能。鎖還是有幫助的,比如有時候,如果一個使用者期望鎖定一個表,因為有使用者會使用insert overwrite這樣的語句去修改表,而同時第2各使用者也在用這個表做查詢,那麼這樣的查詢可能會失敗或者產生無效的結果。使用者可以顯示地管理鎖,例如:

hive>lock table people exclusive;
# 鎖後就不能查詢了,想要查詢可以解鎖
hive>unlock table people;

23.使用count(1)比count(某欄位)來計算行數更快,因為沒有列引用意味著沒有序列化和反序列化的過程,前者會更快。