Hive优化详细讲解

发布于:2025-06-20 ⋅ 阅读:(16) ⋅ 点赞:(0)

目录

一、表设计层面优化

(一)合理设计表结构

(二)使用分区表

(三)使用分桶表

(四)分区 + 分桶——先分区再分桶(优化范围查询)

(五)存储格式

(六)压缩方式

二、数据倾斜层面优化

(一)什么是数据倾斜

(二)数据倾斜发生的原因

(三)如何判断是否发生了数据倾斜

(四)数据倾斜优化办法

三、小文件问题

(一)小文件产生的原因

(二)小文件问题解决方案

四、SQL语句层面

五、配置类型层面优化


一、表设计层面优化

(一)合理设计表结构

包括选择合适的数据类型,避免使用过复杂的数据结构,这会增加序列化和反序列化的开销。

(二)使用分区表

解决 “数据按维度分组存储” 的问题,适合大范围数据过滤。

(三)使用分桶表

分桶数量=总的文件大小/(block size*2)

相关参数设置:

-- 启用自动分桶 join 优化
SET hive.optimize.bucketmapjoin=true;

-- 启用自动排序桶表以进一步优化
SET hive.optimize.bucketmapjoin.sortedmerge=true;

适用条件:

  1. 连接键与分桶键一致两表必须按相同的字段分桶,才能触发同桶连接优化。
  2. 大数据集场景:分桶对 GB 级以上数据集效果更显著,小数据集可能因分桶开销抵消优化收益。

限制:

  1. 分桶数需合理设置:桶数过少可能导致单桶数据量仍较大,桶数过多会增加文件管理开销。
  2. 需手动指定分桶键:建表时需明确分桶键,若业务场景变更(如连接键变化),可能需要重新分桶。

(四)分区 + 分桶——先分区再分桶(优化范围查询)

通过 “先分区过滤维度,再分桶定位分片”,将查询扫描范围从全表级缩小至分区内的桶级,大幅提升查询效率,尤其适用于多条件组合查询场景。

(五)存储格式

存储格式 文件结构 压缩支持 查询性能 适用场景

TextFile

(hive默认存储格式)

纯文本,按行存储,格式简单,广泛兼容 支持(Gzip、BZip2 等) 全表扫描慢,不支持列裁剪 数据导入临时表、小数据集
SequenceFile 二进制键值对 支持(块压缩更佳) 优于 TextFile,支持切片 中间数据存储、MR 作业输入输出
ORC 列式存储 支持(Snappy、ZLIB) 高性能,提供了高效数据压缩,减少存储空间 高频分析查询、大数据集
Parquet 列式存储 支持(Snappy、Gzip) 跨框架兼容,支持嵌套结构 大数据生态通用格式(Spark、Impala)
Avro 二进制格式 + Schema 支持(Snappy、Deflate) 支持 Schema 演进 数据交换、Schema 频繁变更场景

(六)压缩方式

二、数据倾斜层面优化

(一)什么是数据倾斜

        在执行MapReduce作业时,部分reducer处理的数据量远大于其他reducer,这通常是由于某些键(如join操作中的join键或聚合操作中的分组键)的值特别多导致的。

        数据倾斜可能导致查询性能下降,甚至作业失败。

(二)数据倾斜发生的原因

key值分布不均

(三)如何判断是否发生了数据倾斜

1、分析节点资源管理器,如果大部分节点已经执行完成,而个别节点长时间执行不完,很可能发生了数据倾斜。
2、分析执行日志,作业在reduce阶段停留在99%,很长时间完成不了,很可能发生了数据倾斜。

(四)数据倾斜优化办法

        1.通常在数据处理的时候对null值进行赋默认值,当因为重复的空值导致表关联的数据倾斜,可以改写sql,将空值转换成随机值,方便在Map阶段均匀分配;

        2.如果是因为数据类型不一致导致的数据倾斜,我们可以用CAST函数统一数据类型,来避免数据倾斜;

        3.ORDER BY 造成的数据倾斜,可以用distribute BY 和 SORT BY 代替

        4.GROUP BY 造成的数据倾斜,可以通过设置hive参数,设置负载均衡,也可以将倾斜的key单独筛选处理

        5.关于负载均衡: 在Reduce阶段,可以通过设置`hive.exec.reducers.max`来限制最大的Reducer数量,避免某个点的数据过多造成性能瓶颈。  

        6.大表关联小表造成的,可以使用mapjoin将小表数据放在map端处理

        7.大表关联大表终极解决方案是动态一分为二,即对倾斜的键值和不倾斜的键值分开处理,不倾斜的正常join即可,倾斜的把他们找出来做mapjoin,最后union all其结果即可。

但是此种解决方案比较麻烦,代码复杂而且需要一个临时表存放倾斜的键值。

        8.小文件造成的数据倾斜,通过设置hive参数,在map输入端合并小文件,或者在map和reduce输出端合并

        在map输入端合并小文件:(面试最常问)
        使用`mapred.min.split.size`和`mapred.max.split.size`参数可以控制map输入分片的大小。增大这些分片的大小可以减少小文件的数量,从而减少map任务的数量。
        例如:     
        set mapred.min.split.size=256000000;--(即256MB)
        set mapred.max.split.size=256000000;--(即256MB)

     

        在map和reduce输出端合并:
        使用`mapred.merge.recordsBeforeMerge`参数可以设置在启动新的reduce任务之前,从map端发送的记录数。
        增加这个值可以减少在reduce阶段之前需要合并的记录数。
        例如:     
        set mapred.merge.recordsBeforeMerge=100000;

        在发送数据到reducer之前,map任务会累积100000条记录。

三、小文件问题

(一)小文件产生的原因

  1. 往动态分区表插入数据时,会插入大量小文件
  2. reduce的数量设置的较多,到reduce处理时,会分配到不同的reduce中,会产生大量的小文件
  3. 源数据文件就存在大量的小文件
  4. 分桶产生的小文件

(二)小文件问题解决方案

通过设置hive参数,在map输入端合并小文件,或者在map和reduce输出端合并

四、SQL语句层面

  1. 避免全表扫描: 尽量编写能够利用到分区和索引的查询语句,减少全表扫描的情况。
  2. 使用窗口(Analytic Functions): 在需要的时候使用窗口函数,比如`row_number()`, `rank()`等,可以有效减少JOIN操作。
  3. 优化JOIN操作: 尽量减少JOIN操作中的数据集大小,可以使用MAPJOIN或者STREAMING来减少数据的传输。
  4. 使用EXPLAIN计划: 通过EXPLAIN来查看查询计划,找出可能的性能瓶颈。

五、配置类型层面优化

  1. JVM重用: 通过设置参数如`hive.query.rewrite.mapjoins`, `hive.auto.convert.join`等,来控制Map-side join和自动转换普通JOIN到Map-side join。
  2. 内存调整: 调整Hive配置参数,如`hive.tez.container.size`(对于TEZ执行引擎),可以影响任务的并行度和资源使用。
  3. 执行器配置: 设置合理的`hive.exec.reducers.max`, `hive.exec.reducers.min`来控制减少阶段的数量。

网站公告

今日签到

点亮在社区的每一天
去签到