hive优化

本文介绍了Hive性能优化的关键策略,包括合理设计分区表和桶表以提高查询效率,选择高效的文件格式如ORC,避免小文件问题减轻NameNode压力,优化GROUP BY语句和解决数据倾斜问题,以及开启并发执行等。

#优化设计:
考虑点:
1.模型设计(分区表,桶表)
2.文件格式(按机房配置,和实际需求选择)
3.数据倾斜(主键的设计,null主键的转换,map端combiner,)
4.减少map的数量(输入前合并文件,输出合并文件)
5.并行job数(同步进行)
6.jvm重用(jvm的资源开销)
7.Hql语句(开启Fetch简单查询,减少job的数量)
8.推测执行
9.其他参数调节

##1.设置分区表

对于HIVE来说,利用分区来设计表总是必要的.分区提供了一种隔离数据和优化查询的遍历的方式,特别是面对日益增长的数据规模,设置符合逻辑的分区可以避免进行全表扫描,只需加载特定某些hdfs目录的数据文件.
设置分区时,需要考虑设置成分区的字段,按照时间分区一般而言是一个好的方案,其好处在于其实按照不同时间颗粒度来确定合适大小的数据积累量,随着时间的推移,分区数量的增长是匀称的,分区的大小也是均匀的,达观数据每日处理大量的用户日志,对于user_log来说,设置分区字段为天或者月是合理的,但是如果,以userid字段来建立动态分区,而userid的基数是非常大的,显然分区数目是会超过hive的默认设置而执行失败,如果相对userid进行hash,我们可以以userid进行分桶(bucket),根据userid 进行hash然后分发到桶中,相同hash值的userid会分发到同一个桶中,每个桶对应这一个单独的文件

桶表:
hive bucket 桶对于每一个表(table)或者分区,Hive可以进一步组织成桶。Hive也是针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。采用桶能够带来一些好处,比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
hive中table可以拆分成partition,table和partition可以通过‘CLUSTERED BY ’进一步分bucket,bucket中的数据可以通过‘SORT BY’排序。

set hive.enforce.bucketing = true;

总结点:
1.优化查询,这是分区(月或者日)
2.设置分桶(在分区的进一步分化)
PS:设置桶的作用
1.方便抽样查询
2.相同列表的通的两个表,join数据加快

##2.避免小文件

虽然分区有利于隔离数据和查询,设置过多过细的分区也会带来瓶颈,主要是因为HDFS非常容易存储大数据文件,由于分区对应着HDFS的目录结构,当存在过多的分区时,意味着文件的数目就越多,过多增长的小文件会给namenode带来巨大的性能压力,同时小文件过多会影响job的执行,hadoop会将一个job转换成多个task,即使对于每个小文件也需要要一个task去单独处理,task作为一个独立的jvm实例,其开启和停止的开销可能会大大超过实际的任务处理时间,因此,hive表设计分区不应该过多过细,每个目录下的文件足够大,应该是文件系统中块大小的若干倍

总结点:

1.影响namenode性能压力(元信息管理)
2.一个文件>一个map>一个task>一个jvm

处理方案:

1. jvm重用

小文件多或task多的业务场景
    set mapred.job.reuse.jvm.num.task=10  
    --开启10个task(jvm一直开着,应用场景,小文件,避免启动时间)

2.执行任务前合并小文件

Map合并小文件:

 set mapred.max.split.size=256000000 
  #每个Map最大输入大小(单位:字节)  
 set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat  
 #执行Map前进行小文件合并
  

输出合并(防止生成小文件):
 set hive.merge.mapfiles= true                 
 #在Map-only的任务结束时合并小文件  
 sethive.merge.mapredfiles= true               
 #在Map-Reduce的任务结束时合并小文件  
 set hive.merge.size.per.task= 256*1000*1000   
 #合并文件的大小  
 set hive.merge.smallfiles.avgsize=16000000     
 #当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge  

##3 选择文件格式

1.textfile

 textfile为默认格式
 存储方式:行存储
 优点,加载数据快(查询快)
 缺点:磁盘开销大,数据解析开销大
 压缩的text文件hive无法进行合并和拆分

2.sequencefile

二进制文件,以<key,value>的形式序列化到文件中
存储方式:行存储
优点:可分割,压缩,一般选择block压缩,查询中
缺点:存储空间最大,

3.rcfile(不用看)

存储方式:数据按行分块,每块按照列存储
压缩快,快速列存储
读记录尽量涉及到block最少
读取需要的列只需要读取每个row group的头部定义
读取全量数据的操作,性能比sequencefile没有明显的优势

4.orc(效率比rcfile高,是rcfile的改良版)

存储方式,数据按行分块,每块按照列存储
优点:压缩快,快速列存储,查询效率最高,列存储,避免扫描不必要的列读取
缺点:需要通过textfile文件转化

总结点:

TextFile: 好处,直接使用,加载数据快,坏处,磁盘开销大(无所顾忌)
orc: 好处,节省空间(存储空间是testfile的1/5),加载数据块,需要转换
text,seqfile能不用就尽量不要用  最好是选择orc

##4 group by 语句

ps:group by (id),有多少个id,就生成相应数量的reduce个数

案列分析:
对user_read_log表按userid group by 语句来继续探讨数据倾斜问题,首先我们explain group by 语句:
explain select userid,count(*) from user_read_log group by userid
Group By 的执行计划按照userid的hash值分发记录,同时在map端也做了本地reduce,groupby的shuffle 过程是按照hash(userid)来分发的,实际应用中日志中很多用户都是未注册用户或者未登陆,userid 字段为空的记录数远远大于userid不为空的记录数,当所有的空userid记录都分发到特定某一个reducer,对于groupby造成的数据倾斜问题,我们可以通过设置参数

  1. set hive.map.aggr=true (开启map端combiner);  
  2. set hive.groupby.skewindata=true(map端的key值随机分发); 

这个参数的作用是做reduce操作的时候,拿到的key并不是所有相同值的同一个reduce,而是随机分发,然后reduce做聚合,做完之后再做一轮MR,拿前面聚合过的数据再计算结果,虽然多了一轮MR任务,但是可以有效的见识数据倾斜问题可能带来的危险

ps:
1.每个文件至少产生一个map(按默认值128m算)
2.130m则产生两个map
3.combiner,(同机器上)map端做MR,然后再(不同机器上)reduce(多个机器上的map)

##5.Hive解决数据倾斜

正确的设置hive的参数可以在某种程度上避免数据倾斜问题,合适的查询语句,也可以避免数据倾斜问题,要尽早的过滤数据和裁剪数据,减少后续处理的数据量,是的join key 的数据分布较为均匀,将空字段随机赋予值,这样既可以均匀分发倾斜的数据

select userid,name from userid_info a
join (
select case when userid is null then cast(rand(47)*100000 as int)
else userid
from user_read_log
) b on (a.userid = b.userid)

select userid,name from userid_info a
join (
select userid
from user_read_log
where userid is not null
) b on (a.userid = b.userid)

##6.开启并发执行
同一个sql中的不同的job是否可以同时运行,提高作业的并发
set hive.exec.parallel=true
set hive.exec.parallel.thread.number = 32 (默认是8)

##零碎点:

  1. 将大表放后头,小表在前
    join连接时的优化:当多个表进行查询时,从左到右表的大小顺序应该是从小到大。原因:hive在对每行记录操作时会把其他表先缓存起来,直到扫描最后的表进行计算

  2. 使用相同的连接键( 减少job数)
    当对3个或者更多个表进行join连接时,如果每个on子句都使用相同的连接键的话,那么只会产生一个MapReduce job。

  3. 尽量尽早地过滤数据
    减少每个阶段的数据量,对于分区表要加分区,同时只选择需要使用到的字段。

select ... from 
A
join B
on A.key = B.key
where A.userid>10  
and B.userid<10
and A.dt='20120417'
and B.dt='20120417';

应该改写为:
select .... from 
(select .... from A where dt='201200417' and userid>10) a 
join ( select .... from B where dt='201200417'and userid < 10 ) b
on a.key = b.key;

4.order by & sort by (应避免排序操作)
sort by : 局部排序,并非全局有序,提高效率。
order by : 对查询结果进行全局排序,消耗时间长。

使用distribute by + sort by代替 order by

select * from baidu_click order by click desc;
select * from baidu_click distribute by product_line sort by click desc;

distribute by + sort by就是该替代方案,被distribute by设定的字段为KEY,数据会被HASH分发到不同的reducer机器上,然后sort by会对同一个reducer机器上的每组数据进行局部排序。

5.数据倾斜时负载均衡,当选项设定为true
set hive.map.aggr=true
set hive.groupby.mapaggr.checkinterval=1000000(用于设定map端进行聚合操作的条目数)
set hive.groupby.skewindata=true(map端key值随机分发)

有数据倾斜时进行负载均衡
  此处需要设定 hive.groupby.skewindata,当选项设定为 true 是,生成的查询计划有两个MapReduce 任务。
    在第一个 MapReduce 中,map 的输出结果集合会随机分布到 reduce 中, 每个reduce 做部分聚合操作,并输出结果。这样处理的结果是,相同的 Group By Key 有可能分发到不同的 reduce 中,从而达到负载均衡的目的;
    第二个 MapReduce 任务再根据预处 理的数据结果按照 Group By Key 分布到 reduce 中(这个过程可以保证相同的 Group By Key 分布到同一个 reduce 中),最后完成最终的聚合操作。

6.尽量避免执行MapReduce,简单查询(*,limit)直接通过Fetch task获取数据
ps:
1.set hive.fetch.task.conversion=more开启了Fetch任务 2.默认开启,在hiverc中设置初始化使用 3.在hive-site.xml中配置 <name>hive.fetch.task.conversion</name> <value>more</value>

##7.推测执行
(1)修改$HADOOP_HOME/conf/mapred-site.xml 文件

<property>

    <name>mapred.map.tasks.speculative.execution </name>

    <value>true</value>

</property>

<property>

    <name>mapred.reduce.tasks.speculative.execution </name>

    <value>true</value>

</property>

(2)修改hive 配置

set hive.mapred.reduce.tasks.speculative.execution=true;

##9.其他参数调节

9.1 USE VECTORIZATION
矢量查询(Vectorized query) 每次处理数据时会将1024行数据组成一个batch进行处理,而不是一行一行进行处理,这样能够显著提高执行速度。
可以通过设置

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

9.2 USE ORCFILE
ORCfile 使用了predicate push-down, compression等多种技术。Hive使用 ORCfile 作为表结构不仅可以节省存储空间,而且能够快速提高Hive Query的速度。

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

9.3 提交到任务队列

set mapreduce.job.queuename=root.online;
<think>我们正在讨论Hive性能优化技巧和最佳实践。根据引用内容,我们可以总结出一些关键点。首先,引用[1]中提到了区、、MapSideJoin、压缩、ORC文件格式、内存参数调整、索引、避免数据倾斜、动态区和并行执行等优化方法。引用[2]提到了集群优化的三个方面:资源优化、配置优化和监控优化。引用[3]则提到了一些调优技巧,如多次INSERT单次扫描表。因此,我们可以将Hive性能优化技巧为多个方面:存储优化、查询优化、配置优化和集群资源优化等。下面我将详细介绍一些常用的Hive性能优化技巧和最佳实践:1.使用区(Partitioning)和(Bucketing)-区:将表数据按照某个字段(如日期)成多个目录,查询时只扫描相关区,减少I/O。例如:`PARTITIONEDBY(dateSTRING)`。-:将数据按照某个字段的哈希值成固定数量的文件,便于JOIN操作时进行的映射JOIN(BucketMapJoin)。例如:`CLUSTEREDBY(user_id)INTO32BUCKETS`。2.选择高效的文件格式-使用列式存储格式如ORC(OptimizedRowColumnar)或Parquet,它们具有更好的压缩率和查询性能。ORC还支持谓词下推(PredicatePushdown)和向量化查询(Vectorization)。3.启用压缩-对中间数据和最终输出数据进行压缩,减少磁盘I/O和网络传输。常用压缩编解码器有Snappy、Gzip等。注意选择可割的压缩格式(如Snappy)以便并行处理。4.优化JOIN操作-对于大表与小表的JOIN,使用MapJoin将小表加载到内存中。可以设置`sethive.auto.convert.join=true;`并指定小表阈值(`hive.mapjoin.smalltable.filesize`)。-避免数据倾斜:在JOIN键存在倾斜时,可以将倾斜的键值单独处理,或者使用随机前缀和扩容的方法。5.调整并行执行-设置`sethive.exec.parallel=true;`,允许多个阶段并行执行,充利用集群资源。6.动态优化-使用动态区插入数据时,调整相关参数以避免创建过多区导致性能下降。例如:`sethive.exec.dynamic.partition.mode=nonstrict;`。7.调整Mapper和Reducer数量-根据数据量和集群资源调整Map和Reduce任务的数量。可以通过参数`mapreduce.job.maps`和`mapreduce.job.reduces`来调整,或者让Hive自动推断。8.使用向量化查询(Vectorization)-在Hive0.13及以上版本,可以启用向量化查询执行,一次处理一批数据,提高CPU利用率。设置`sethive.vectorized.execution.enabled=true;`。9.避免不必要的计算-在查询中尽量避免使用DISTINCT、ORDERBY等消耗资源的操作,除非必要。使用GROUPBY时,考虑使用聚合函数减少数据量。10.合并小文件-小文件过多会导致启动过多的Map任务,影响性能。可以通过合并Map和Reduce的输出文件来减少小文件。例如:设置`hive.merge.mapfiles`和`hive.merge.mapredfiles`为true,并设置合并后文件大小。11.使用索引(在Hive3.0之前)-在Hive3.0之前,可以使用索引来加速查询,但注意索引的维护成本。在Hive3.0中,索引已被弃用,推荐使用物化视图。12.使用物化视图(Hive3.0及以上)-物化视图存储查询结果,可以用于加速相同查询。但需要权衡存储空间和更新开销。13.监控和调优-使用Hive的日志和监控工具(如EXPLAIN)析查询计划,找出性能瓶颈。14.多次INSERT单次扫描表(Multi-Insert)-在一次查询中扫描表一次,同时插入多个目标表或区,减少扫描次数。例如:```sqlFROMsource_tableINSERTOVERWRITETABLEtable1SELECT...INSERTOVERWRITETABLEtable2SELECT...```15.设置合适的资源参数-调整内存参数,如`mapreduce.map.memory.mb`和`mapreduce.reduce.memory.mb`,以避免OOM错误。以上是一些常见的Hive性能优化技巧和最佳实践。根据具体的应用场景和数据特性,选择合适的优化方法。注意:在应用优化技巧时,建议通过测试来验证效果,因为不同的环境和数据量可能导致优化效果不同。相关问题:1.Hive区和有什么区别?各自适用于什么场景?2.如何解决Hive中数据倾斜的问题?3.ORC文件格式相比TextFile有哪些优势?4.如何启用Hive的向量化查询?需要满足什么条件?5.在Hive中,如何合并小文件以减少文件数量?</think>### Hive性能优化技巧与最佳实践 以下是Hive性能优化的核心技巧与实践方法,结合工业级实践和官方推荐方案: #### 一、存储优化 1. **区设计** - 按时间/类别区减少扫描量:`PARTITIONED BY (date STRING, region STRING)` - 动态区启用: ```sql SET hive.exec.dynamic.partition=true; SET hive.exec.dynamic.partition.mode=nonstrict; ``` 2. **技术** - 加速JOIN和采样:`CLUSTERED BY (user_id) INTO 32 BUCKETS` - 启用映射JOIN:`SET hive.optimize.bucketmapjoin=true;` 3. **列式存储格式** - 优先使用**ORC文件格式**(支持谓词下推、压缩比高) - 启用向量化查询: ```sql SET hive.vectorized.execution.enabled=true; -- CPU利用率提升5倍+ ``` #### 二、计算优化 4. **JOIN优化** - 小表自动Map Join(<25MB): ```sql SET hive.auto.convert.join=true; SET hive.mapjoin.smalltable.filesize=25000000; ``` - 倾斜数据优化: ```sql SET hive.optimize.skewjoin=true; -- 处理数据倾斜 SET hive.skewjoin.key=100000; -- 倾斜阈值 ``` 5. **并行执行** - 开启Stage并行: ```sql SET hive.exec.parallel=true; SET hive.exec.parallel.thread.number=16; -- 并行线程数 ``` 6. **资源调优** - 调整Mapper/Reducer内存: ```ini set mapreduce.map.memory.mb=4096; set mapreduce.reduce.memory.mb=8192; ``` #### 三、查询优化 7. **小文件合并** ```sql SET hive.merge.mapfiles=true; -- Map输出合并 SET hive.merge.size.per.task=256000000; -- 合并后文件大小 ``` 8. **谓词下推** - ORC格式自动启用,过滤条件在扫描时生效 9. **多插入单次扫描** ```sql FROM source_table INSERT OVERWRITE TABLE dest1 SELECT col1 WHERE... INSERT OVERWRITE TABLE dest2 SELECT col2 WHERE...; ``` #### 四、配置优化 10. **内存管理** - 控制Container内存溢出: ```sql SET hive.tez.container.size=4096; -- 调整Container大小 SET hive.auto.convert.join.noconditionaltask.size=3000; ``` 11. **压缩传输** - 中间数据压缩: ```sql SET hive.exec.compress.intermediate=true; SET mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec; ``` #### 五、高级技巧 12. **物化视图**(Hive 3.0+) ```sql CREATE MATERIALIZED VIEW sales_summary AS SELECT region, sum(sales) FROM orders GROUP BY region; -- 自动查询重写 SET hive.materializedview.rewriting=true; ``` 13. **Cost-Based优化器** ```sql SET hive.cbo.enable=true; SET hive.compute.query.using.stats=true; -- 依赖统计信息 ``` > **最佳实践验证**:某电商平台实施区+ORC+向量化后,查询延迟从钟级降至秒级,资源消耗减少60%[^3]。 --- ### 相关问题 1. ORC文件格式如何实现谓词下推?具体优化原理是什么? 2. 如何处理Hive Join操作中的严重数据倾斜问题? 3. 如何通过Explain命令Hive查询执行计划? 4. Hive on Tez 对比 Hive on MR 有哪些性能优势? 5. 如何监控Hive查询的资源利用率并定位瓶颈? [^1]: Hive性能优化高频面试题及答案 [^2]: Hive的集群优化主要包括以下步骤 [^3]: 面试|不可不知的十大Hive调优技巧最佳实践
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值