1. 程式人生 > >深入淺出學Hive——Hive QL

深入淺出學Hive——Hive QL

•指定了LOCAL •load 命令會去查詢本地檔案系統中的 filepath。如果發現是相對路徑,則路徑會被解釋為相對於當前使用者的當前路徑。使用者也可以為本地檔案指定一個完整的 URI,比如:file:///user/hive/project/data1. •load 命令會將 filepath 中的檔案複製到目標檔案系統中。目標檔案系統由表的位置屬性決定。被複制的資料檔案移動到表的資料對應的位置 • 沒有指定LOCAL          如果 filepath 指向的是一個完整的 URI,hive 會直接使用這個 URI。 否則 •如果沒有指定 schema 或者 authority,Hive 會使用在 hadoop 配置檔案中定義的 schema 和 authority,fs.default.name 指定了 Namenode 的 URI •如果路徑不是絕對的,Hive 相對於 /user/ 進行解釋。 Hive 會將 filepath 中指定的檔案內容移動到 table (或者 partition)所指定的路徑中 OVERWRITE •指定了OVERWRITE •目標表(或者分割槽)中的內容(如果有)會被刪除,然後再將 filepath 指向的檔案/目錄中的內容新增到表/分割槽中。 •如果目標表(分割槽)已經有一個檔案,並且檔名和 filepath 中的檔名衝突,那麼現有的檔案會被新檔案所替代。 將查詢結果插入Hive表 •將查詢結果插入Hive表 •將查詢結果寫入HDFS檔案系統 •基本模式      INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement •多插入模式  FROM from_statement INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 [INSERT OVERWRITE TABLE tablename2 [PARTITION ...] select_statement2] ... •自動分割槽模式  INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement 將查詢結果寫入HDFS
檔案系統
•INSERT OVERWRITE [LOCAL] DIRECTORY directory1 SELECT ... FROM ...         FROM from_statement         INSERT OVERWRITE [LOCAL] DIRECTORY directory1 select_statement1      [INSERT OVERWRITE [LOCAL] DIRECTORY directory2 select_statement2] • •資料寫入檔案系統時進行文字序列化,且每列用^A 來區分,\n換行 INSERT INTO  •INSERT INTO  TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement 第三部分:HiveQL 查詢操作
SQL操作 •基本的Select 操作 •基於Partition的查詢 •Join 基本的Select 操作 SELECT [ALL | DISTINCT] select_expr, select_expr, ... FROM table_reference [WHERE where_condition] [GROUP BY col_list [HAVING condition]] [   CLUSTER BY col_list   | [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list] ] [LIMIT number] •使用ALL和DISTINCT選項區分對重複記錄的處理。預設是ALL,表示查詢所有記錄。DISTINCT表示去掉重複的記錄 • •Where 條件 •類似我們傳統SQL的where 條件 •目前支援 AND,OR ,0.9版本支援between •IN, NOT IN •不支援EXIST ,NOT EXIST ORDER BY
SORT BY的不同
•ORDER BY 全域性排序,只有一個Reduce任務 •SORT BY 只在本機做排序 Limit •Limit 可以限制查詢的記錄數 SELECT * FROM t1 LIMIT 5 •實現Top k 查詢 •下面的查詢語句查詢銷售記錄最大的 5 個銷售代表。 SET mapred.reduce.tasks = 1 
  SELECT * FROM test SORT BY amount DESC LIMIT 5 •REGEX Column Specification SELECT 語句可以使用正則表示式做列選擇,下面的語句查詢除了 ds 和 hr 之外的所有列: SELECT `(ds|hr)?+.+` FROM test 基於Partition的查詢 •一般 SELECT 查詢會掃描整個表,使用 PARTITIONED BY 子句建表,查詢就可以利用分割槽剪枝(input pruning)的特性 •Hive 當前的實現是,只有分割槽斷言出現在離 FROM 子句最近的那個WHERE 子句中,才會啟用分割槽剪枝 Join Syntax 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: 
    table_factor 
  | join_table 

table_factor: 
    tbl_name [alias] 
  | table_subquery alias 
  | ( table_references ) 

join_condition: 
    ON equality_expression ( AND equality_expression )* 

equality_expression: 
    expression = expression •Hive 只支援等值連線(equality joins)、外連線(outer joins)和(left semi joins)。Hive 不支援所有非等值的連線,因為非等值連線非常難轉化到 map/reduce 任務 •LEFT,RIGHT和FULL OUTER關鍵字用於處理join中空記錄的情況 •LEFT SEMI JOIN 是 IN/EXISTS 子查詢的一種更高效的實現 •join 時,每次 map/reduce 任務的邏輯是這樣的:reducer 會快取 join 序列中除了最後一個表的所有表的記錄,再通過最後一個表將結果序列化到檔案系統 •實踐中,應該把最大的那個表寫在最後 join 查詢時,需要注意幾個關鍵點 •只支援等值join •SELECT a.* FROM a JOIN b ON (a.id = b.id) •SELECT a.* FROM a JOIN b 
    ON (a.id = b.id AND a.department = b.department) •可以 join 多於 2 個表,例如   SELECT a.val, b.val, c.val FROM a JOIN b 
    ON (a.key = b.key1) JOIN c ON (c.key = b.key2) •如果join中多個表的 join key 是同一個,則 join 會被轉化為單個 map/reduce 任務 LEFTRIGHTFULL OUTER •例子 •SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key) •如果你想限制 join 的輸出,應該在 WHERE 子句中寫過濾條件——或是在 join 子句中寫 • •容易混淆的問題是表分割槽的情況 • SELECT c.val, d.val FROM c LEFT OUTER JOIN d ON (c.key=d.key) 
  WHERE a.ds='2010-07-07' AND b.ds='2010-07-07‘ •如果 d 表中找不到對應 c 表的記錄,d 表的所有列都會列出 NULL,包括 ds 列。也就是說,join 會過濾 d 表中不能找到匹配 c 表 join key 的所有記錄。這樣的話,LEFT OUTER 就使得查詢結果與 WHERE 子句無關 •解決辦法 •SELECT c.val, d.val FROM c LEFT OUTER JOIN d 
  ON (c.key=d.key AND d.ds='2009-07-07' AND c.ds='2009-07-07') LEFT SEMI JOIN •LEFT SEMI JOIN 的限制是, JOIN 子句中右邊的表只能在 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) UNION ALL •用來合併多個select的查詢結果,需要保證select中欄位須一致 •select_statement UNION ALL select_statement UNION ALL select_statement ... 第四部分:從SQL到HiveQL應該轉變的幾個習慣 Hive不支援等值連線 •SQL中對兩表內聯可以寫成: •select * from dual a,dual b where a.key = b.key; •Hive中應為 •select * from dual a join dual b on a.key = b.key;    分號字元 •分號是SQL語句結束標記,在HiveQL中也是,但是在HiveQL中,對分號的識別沒有那麼智慧,例如: •select concat(key,concat(';',key)) from dual; •但HiveQL在解析語句時提示:         FAILED: Parse Error: line 0:-1 mismatched input '<EOF>' expecting ) in function specification •解決的辦法是,使用分號的八進位制的ASCII碼進行轉義,那麼上述語句應寫成: •select concat(key,concat('\073',key)) from dual; IS [NOT] NULL •SQL中null代表空值, 值得警惕的是, 在HiveQL中String型別的欄位若是空(empty)字串, 即長度為0, 那麼對它進行IS NULL的判斷結果是False.