Hive 随谈(五)– Hive 优化

本文介绍了Hive查询优化策略,包括列裁剪、分区裁剪、Join操作优化、Map端部分聚合等内容。通过这些策略可以有效提升Hive查询效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hive 针对不同的查询进行了优化,优化可以通过配置进行控制,本文将介绍部分优化的策略以及优化控制选项。

列裁剪(Column Pruning)

在读数据的时候,只读取查询中需要用到的列,而忽略其他列。例如,对于查询:

SELECT a,b FROM T WHERE e < 10;

其中,T 包含 5 个列 (a,b,c,d,e),列 c,d 将会被忽略,只会读取a, b, e 列

这个选项默认为真: hive.optimize.cp = true

分区裁剪(Partition Pruning)

在查询的过程中减少不必要的分区。例如,对于下列查询:

SELECT * FROM (SELECT c1, COUNT(1)
FROM T GROUP BY c1) subq
WHERE subq.prtn = 100;

SELECT * FROM T1 JOIN
(SELECT * FROM T2) subq ON (T1.c1=subq.c2)
WHERE subq.prtn = 100;

会在子查询中就考虑 subq.prtn = 100 条件,从而减少读入的分区数目。

此选项默认为真:hive.optimize.pruner=true

Join

在使用写有 Join 操作的查询语句时有一条原则:应该将条目少的表/子查询放在 Join 操作符的左边。原因是在 Join 操作的 Reduce 阶段,位于 Join 操作符左边的表的内容会被加载进内存,将条目少的表放在左边,可以有效减少发生 OOM 错误的几率。

对于一条语句中有多个 Join 的情况,如果 Join 的条件相同,比如查询:

INSERT OVERWRITE TABLE pv_users
SELECT pv.pageid, u.age FROM page_view p
JOIN user u ON (pv.userid = u.userid)
JOIN newuser x ON (u.userid = x.userid);
  • 如果 Join 的 key 相同,不管有多少个表,都会则会合并为一个 Map-Reduce
  • 一个 Map-Reduce 任务,而不是 ‘n’ 个
  • 在做 OUTER JOIN 的时候也是一样

如果 Join 的条件不相同,比如:

INSERT OVERWRITE TABLE pv_users
SELECT pv.pageid, u.age FROM page_view p
JOIN user u ON (pv.userid = u.userid)
JOIN newuser x on (u.age = x.age);

Map-Reduce 的任务数目和 Join 操作的数目是对应的,上述查询和以下查询是等价的:

INSERT OVERWRITE TABLE tmptable
SELECT * FROM page_view p JOIN user u
ON (pv.userid = u.userid);

INSERT OVERWRITE TABLE pv_users
SELECT x.pageid, x.age FROM tmptable x
JOIN newuser y ON (x.age = y.age);
Map Join

Join 操作在 Map 阶段完成,不再需要Reduce,前提条件是需要的数据在 Map 的过程中可以访问到。比如查询:

INSERT OVERWRITE TABLE pv_users
SELECT /*+ MAPJOIN(pv) */ pv.pageid, u.age
FROM page_view pv
JOIN user u ON (pv.userid = u.userid);

可以在 Map 阶段完成 Join,如图所示:

相关的参数为:

  • hive.join.emit.interval = 1000 How many rows in the right-most join operand Hive should buffer before emitting the join result.
  • hive.mapjoin.size.key = 10000
  • hive.mapjoin.cache.numrows = 10000
Group By
  • Map 端部分聚合:
    • 并不是所有的聚合操作都需要在 Reduce 端完成,很多聚合操作都可以先在 Map 端进行部分聚合,最后在 Reduce 端得出最终结果。
    • 基于 Hash
    • 参数包括:
      • hive.map.aggr = true 是否在 Map 端进行聚合,默认为 True
      • hive.groupby.mapaggr.checkinterval = 100000 在 Map 端进行聚合操作的条目数目
  • 有数据倾斜的时候进行负载均衡
    • hive.groupby.skewindata = false
    • 当选项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。
合并小文件

文件数目过多,会给 HDFS 带来压力,并且会影响处理效率,可以通过合并 Map 和 Reduce 的结果文件来消除这样的影响:

  • hive.merge.mapfiles = true 是否和并 Map 输出文件,默认为 True
  • hive.merge.mapredfiles = false 是否合并 Reduce 输出文件,默认为 False
  • hive.merge.size.per.task = 256*1000*1000 合并文件的大小

Hive 是一个基于 Hadoop 构建的**数据仓库工具**,它允许用户通过类 SQL 的查询语言(HQL)对存储在 HDFS 中的大规模数据进行读取、写入和管理。Hive 适用于结构化数据的批处理分析任务,广泛应用于大数据平台的数据仓库建设中。 ### Hive 的核心概念 - **表(Table)**:与传统数据库类似,Hive 表由行和列组成,每列有特定的数据类型。 - **分区(Partition)**:用于将数据按照某个维度(如日期、地区等)划分到不同的目录下,从而提高查询效率。 - **分桶(Bucket)**:进一步对分区数据进行哈希划分,使得数据分布更均匀,便于高效采样和连接操作。 - **外部表(External Table)**:与内部表不同,删除外部表时不会删除其对应的数据文件,适合多系统共享数据的场景。 - **SerDe(Serializer/Deserializer)**:定义数据如何从文件格式转换为 Hive 表中的结构化数据,常见的 SerDe 包括 `LazySimpleSerDe`、`RegexSerDe` 和 `JSONSerDe` 等。 ### Hive 查询语言(HQL) Hive 提供了丰富的类 SQL 操作: - **DDL(Data Definition Language)**: - 创建数据库、表、视图 - 修改表结构(如添加列) - 删除对象 - **DML(Data Manipulation Language)**: - 插入数据(`INSERT INTO`, `INSERT OVERWRITE`) - 加载数据(`LOAD DATA INPATH`) - 查询数据(`SELECT`, `JOIN`, `GROUP BY`, `ORDER BY`) - **HiveQL 扩展功能**: - 使用 `LATERAL VIEW` 与 `explode()` 处理复杂嵌套结构 - 使用 `WINDOWING` 实现窗口函数 - 支持自定义函数(UDF、UDAF、UDTF) ### Hive 性能优化技巧 - **分区与分桶**:合理设计分区字段和分桶数量可以显著提升查询性能。 - **压缩与存储格式**:使用高效的存储格式(如 ORCFile、Parquet)并启用压缩(如 Snappy、Gzip)可减少 I/O 开销。 - **动态分区插入**:启用 `hive.exec.dynamic.partition.mode=nonstrict` 可以支持动态分区插入。 - **小文件合并**:使用 `CombineHiveInputFormat` 或配置参数自动合并小文件,避免 Map 数量过多。 - **JVM 重用**:设置 `mapreduce.task.timeout=0` 并启用 JVM 重用,减少任务启动开销。 ### Hive 学习资源推荐 1. **官方文档**: - [Apache Hive 官方文档](https://cwiki.apache.org/confluence/display/Hive/Home) 2. **书籍推荐**: - 《Programming Hive》 – Edward Capriolo, Dean Wampler, Jason Rutherglen - 《Hive: The Definitive Guide》 – James Sulton 3. **在线课程**: - Coursera 上的《Big Data Analytics Using Hive》 - Udemy 上的《Hive for Beginners》 4. **实战练习平台**: - [HackerRank](https://www.hackerrank.com/) - [LeetCode](https://leetcode.com/)(部分题目涉及 Hive) - [Kaggle Datasets + Notebooks](https://www.kaggle.com/datasets) ### Hive 期末考试常见题型汇总 #### 选择题示例 1. Hive 是基于以下哪个框架构建的? - A) Spark - B) Flink - C) Hadoop - D) Kafka **答案:C** 2. Hive 不适合用于哪种场景? - A) 批量数据分析 - B) 实时流处理 - C) 数据仓库构建 - D) 日志聚合分析 **答案:B** #### 填空题示例 1. Hive 中用于将数据按某一列进行哈希划分的机制称为 ________。 **答案:分桶(Bucketing)** 2. Hive 中的外部表被删除后,对应的 HDFS 文件 ________。 **答案:不会被删除** #### 简答题示例 1. 简述 Hive 分区与分桶的区别及其适用场景。 **参考要点**: - 分区适用于按时间或地域划分数据,便于过滤 - 分桶适用于连接操作和采样,使数据分布更均匀 2. Hive 支持哪些常见的 SerDe?请列举三个并说明其用途。 **参考答案**: - `LazySimpleSerDe`:默认 SerDe,用于 CSV、TSV 等简单文本格式 - `RegexSerDe`:用于正则表达式匹配的非结构化日志数据 - `JSONSerDe`:用于解析 JSON 格式的输入数据 #### 编程题示例 1. 假设有一个订单表 `orders(order_id STRING, customer_id STRING, amount DOUBLE, order_date STRING)`,请写出一条 HiveQL 查询语句,统计每个客户的总消费金额,并按金额降序排列前 10 名客户。 ```sql SELECT customer_id, SUM(amount) AS total_amount FROM orders GROUP BY customer_id ORDER BY total_amount DESC LIMIT 10; ``` 2. 使用 HiveQL 将一个已有的表 `old_table` 的结构复制到新表 `new_table`,但不复制数据。 ```sql CREATE TABLE new_table LIKE old_table; ``` ### Hive 复习指南 | 主题 | 重点内容 | |------|----------| | Hive 架构与原理 | HiveServer2、Metastore、执行引擎、MapReduce 与 Tez 引擎对比 | | 数据模型 | 内部表 vs 外部表、分区、分桶、索引 | | 数据导入导出 | LOAD DATA、INSERT OVERWRITE、导出至本地文件 | | 查询语法 | SELECT、JOIN、GROUP BY、子查询、窗口函数 | | 性能调优 | 分区剪枝、列裁剪、压缩、执行引擎选择 | | Hive 与 Hadoop 生态集成 | HDFS、HBase、Spark 集成方式 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值