[Hive 進階]-- 7種可以提高 Hive 查詢速度的方法

如何提高Hive 的查詢性能?

Apache Hive是一種強大的數據分析工具。在處理數PB的數據時,瞭解如何提高查詢性能非常重要。以下內容是基於 HDP-2.6.4 版本彙總的,如有不足之處,望指出。

1、使用Tez引擎

Apache Tez Engine是一個可擴展的框架,用於構建高性能批處理和交互式數據處理。它由YARN在Hadoop中 調度。Tez通過提高處理速度和保持MapReduce擴展到數PB數據的能力來改進MapReduce job。

通過設置hive.execution.engine 爲tez:可以在環境中啓用Tez引擎:

set hive.execution.engine=tez;

2、使用向量化

向量化通過在單個操作中獲取 1024 行而不是 每次只獲取單行來改善 scans, aggregations, filters 和 join 這類操作的性能。

我們可以通過執行以下命令在環境中啓用向量化:

set hive.vectorized.execution.enabled=true;

set hive.vectorized.execution.reduce.enabled=true;

3、使用ORCFile

  • Hive 支持 ORCfile,這是一種新的表存儲格式,在讀取,寫入和處理數據時,ORCFile格式優於Hive文件格式,它通過 predicate push-down, compression 等技術來提高查詢速度。
  • 在 HIVE 表中使用 ORCFile,將有益於獲得 HIVE 快速響應的查詢。
  • ORCFile 格式通過對原始數據存儲量壓縮75%,提供了高效的存儲 Hive 數據的方法。

舉例,考慮兩個大表 A 和 B(存儲爲 TextFIle,這裏沒有指定一些列),使用一個簡單的查詢,如:

SELECT A.customerID,
       A.name,
       A.age,
       A.address
JOIN B.role,
     B.department,
     B.salary ON A.customerID=B.customerID;

由於表 A 和表 B 都存儲爲 TextFile,因此執行此查詢可能需要很長時間。
將這些表存儲格式轉換爲 ORCFile 格式通常會明顯減少查詢時間:

CREATE TABLE A_ORC ( 
customerID int, 
name string,
age int, 
address string 
) STORED AS ORC tblproperties (“orc.compress" = “SNAPPY”)
;


INSERT INTO TABLE A_ORC
SELECT *
FROM A
;


CREATE TABLE B_ORC ( 
customerID int, 
ROLE string,
salary float, 
department string 
) STORED AS ORC tblproperties (“orc.compress" = “SNAPPY”)
;


INSERT INTO TABLE B_ORC
SELECT *
FROM B
;


SELECT A_ORC.customerID,
       A_ORC.name,
       A_ORC.age,
       A_ORC.address
JOIN B_ORC.role,
     B_ORC.department,
     B_ORC.salary ON A_ORC.customerID=B_ORC.customerID
;

ORC 支持壓縮存儲(使用 ZLIB 或如上所示使用 SNAPPY),但也支持不壓縮存儲。

4、使用分區

通過分區,數據存儲在 HDFS 上的單獨單個文件夾中。Hive 將查詢分區數據集,而不是 掃描表的所有數據集。

創建臨時表並將數據加載到臨時表中

CREATE TABLE Employee_Temp(
EmloyeeID int, 
EmployeeName Varchar(100),
Address Varchar(100),
STATE Varchar(100),
City Varchar(100),
Zipcode Varchar(100)
) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS TEXTFILE;

LOAD DATA INPATH '/home/hadoop/hive' INTO TABLE Employee_Temp;

創建分區表


Create Table Employee_Part(
EmloyeeID int, 
EmployeeName Varchar(100), 
Address Varchar(100),
State Varchar(100),
Zipcode Varchar(100))
PARTITIONED BY (City Varchar(100))
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE;

啓用動態分區的命令


SET hive.exec.dynamic.partition = true;
SET hive.exec.dynamic.partition.mode = nonstrict;

從臨時表導入數據到分區表

INSERT Overwrite TABLE Employee_Part Partition(City)
SELECT EmployeeID,
       EmployeeName,
       Address,
       STATE,
       City,
       Zipcode
FROM Emloyee_Temp;

5、使用 分桶

桶表介紹:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL+BucketedTables

舉例:https://blog.csdn.net/m0_37534613/article/details/55258928

Hive 表被劃分爲多個分區,稱爲 Hive分區。Hive分區進一步細分爲集羣或桶,稱爲 bucket 或 Cluster。

Create Table Employee_Part(
EmloyeeID int, 
EmployeeName Varchar(100), 
Address Varchar(100),
State Varchar(100),
Zipcode Varchar(100))
PARTITIONED BY (City Varchar(100))
Clustered By (EmployeeID) into 20 Buckets
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE;

6、CBO 查詢優化器

Hive CBO 是使用 Apache calcite 來處理的。

  • 早期的 Hive 版本中(Hive-0.14 之前),在提交最終執行之前,Hive 會優化每個查詢的邏輯和物理執行計劃。 這些優化不是基於查詢的成本優化(Cost-based Optimizer) 。
  • 直到 Hive-0.14 時才添加了 Cost-based optimization ,這時已經根據查詢的成本進行優化(例如要執行的連接類型,如何排序連接,並行度等)。

要使用基於成本的優化,需要在查詢開頭設置以下參數

set hive.cbo.enable=true;
set hive.compute.query.using.stats=true;
set hive.stats.fetch.column.stats=true;
set hive.stats.fetch.partition.stats=true;

如果要收集表信息,請使用 Analyze 命令。

7、寫好的 SQL

SQL是一種強大的聲明性語言。 與其他聲明性語言一樣,編寫SQL語句的方法不止一種。 
儘管每個語句的功能都相同,但它可能具有截然不同的性能特徵。
我們來看一個例子。 考慮點擊流事件表:

CREATE TABLE clicks (

timestamp date, sessionID string, url string, source_ip string

) STORED as ORC tblproperties (“orc.compress” = “SNAPPY”);

每條記錄代表一次點擊事件,我們希望找到每個sessionID的最新網址。
有人可能會考慮以下方法:

SELECT clicks.* FROM clicks inner join

(select sessionID, max(timestamp) as max_ts from clicks

group by sessionID) latest

ON clicks.sessionID = latest.sessionID and

clicks.timestamp = latest.max_ts;

在上面的查詢中,我們構建一個子查詢來收集每個會話中最新事件的時間戳,然後使用 內聯接 來過濾掉其餘的事件。
雖然查詢是一個合理的解決方案, 但是從功能的角度來看 ,有一種更好的方法來重寫這個查詢,如下所示:

SELECT * FROM

(SELECT *, RANK() over (partition by sessionID,

order by timestamp desc) as rank

FROM clicks) ranked_clicks

WHERE ranked_clicks.rank=1;

在這裏,我們使用 Hive 的 OLAP 窗口功能(OVER 和 RANK)來實現相同的功能。
顯然,刪除不必要的連接幾乎總能帶來更好的性能,而且當使用大數據時,這比以往任何時候都更重要。 
我發現很多情況下查詢不是最優的 - 所以仔細查看每個查詢並考慮重寫是否可以使它更好更快。

小結

Apache Hive是一個非常強大的數據分析工具,它支持批處理和交互式數據處理。 
它是數據分析師和數據科學家最常用的技術之一。 在處理數PB的數據時,瞭解如何提高查詢性能非常重要。以上彙總僅供參考!

參考

  1. https://cwiki.apache.org/confluence/display/Hive/StatsDev
  2. https://zh.hortonworks.com/blog/5-ways-make-hive-queries-run-faster/
  3. https://dzone.com/articles/how-to-improve-hive-query-performance-with-hadoop
  4. https://cwiki.apache.org/confluence/display/Hive/LanguageManual+WindowingAndAnalytics

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章