深入淺出學Hive——Hive QL
阿新 • • 發佈:2019-02-10
•指定了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 任務 LEFT,RIGHT和FULL 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.
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 任務 LEFT,RIGHT和FULL 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.