[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

 

    原文作者:highfei2011
    原文地址: https://blog.csdn.net/high2011/article/details/96271903
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞