hive优化总结

在hive体系结构文章中我们说过hive的执行依赖于底层的MapReduce作业,因此对hadoop作业的优化或者对MapReduce作业的调整是提高hive性能的基础。如果没有适当的调整,即使查询hive中的一个小表,有时也会耗时数分钟才会得到结果。在此我们通过下面几种方式的调整,可以大大提高hive的性能。

1.启用压缩

 压缩可以使磁盘上存储的数据量变小,对于文本文件格式能够压缩45%甚至更高的比例,这样可以通过降低I/O来提高查询速度。除非产生的数据用于外部系统,否则建议总是开启压缩策略。虽然压缩与解压缩会耗用一定的cpu资源,但hive产生的MapReduce作业一般都是IO密集型的,所以cpu开销一般不是问题。

我们可以通过 set io.compression.codecs;查看支持的压缩及解压缩算法,如没有需自行配置安装。

当一个复杂的hive查询提交后,会经历一系列的中间阶段的MapReduce作业,我们可以通过将这些中间运行中的数据压缩,来提高执行效率。在hive-site.xml 中通过设置hive.exec.compress.intermediate属性来启动中间数据压缩。

当然我们也可以在hive端使用set命令来设置:

当hive将输出写入到表时,输出的内容也是可以进行压缩的,我们可以通过hive.exec.compress.output属性启用输出压缩。

<property>
  <name>hive.exec.compress.output</name>
  <value>true</value>
</property>

或者

set hive.exec.compress.output=true;
set mapreduce.output.fileoutputformat.compress=true;
set mapreduce.output.fileoutputformat.compress.codec=org.apache.io.compress.SnappyCodec;
set mapreduce.output.fileoutputformat.compress.type=BLOCK;

2.优化连接

<1>自动map连接

      当连接一个大表和一个小表时,如果启用了自动map连接,小标将保存在每个节点的本地缓存中,并在map阶段与大表进行连接。这样做有俩个明显的好处,首先是将小表装进缓存将节省每个节点上的数据读取时间,其次,避免了在hive查询中的数据倾斜,因为每个数据块的连接操作在map阶段已经完成。启用以下配置将开启自动map连接属性:

<property>
  <name>hive.auto.convert.join</name>
  <value>true</value>
</property>
<property>
  <name>hive.auto.convert.join.noconditionaltask</name>
  <value>true</value>
</property>
<property>
  <name>hive.auto.convert.join.noconditionaltask.size</name>
  <value>10000000</value>
</property>
<property>
  <name>hive.auto.convert.join.use.nonstaged</name>
  <value>true</value>
</property>

说明:
hive.auto.convert.join:是否启用基于输入文件的大小,将普通连接转化为Map连接的优化机制。
hive.auto.convert.join.noconditionaltask:是否启用基于输入文件的大小,将普通连接转为map连接的
     优化机制,假如参与连接的表(或者分区)有n个,如果打开这个参数,此时如果n-1个表(或分区)的总
     大小小于hive.auto.convert.join.noconditionaltask.size指定的值,那么会将次查询转化为Map
     连接。

hive.auto.convert.join.noconditionaltask.size:如果参与连接的N个表中的N-1个总大小小于此参数
     值,直接将连接转为map连接。默认值为10M.
hive.auto.convert.join.use.nonstaged:对于条件连接,如果从一个小的输入流可以应用于join操作,而
     不需要过滤,那么不需要通过MapReduce的本地任务在分布式缓存中预存。注意,该参数在
     vectorization或者tez执行引擎中是不起作用的。

<2>倾斜连接

    当俩个大表进行连接时,会先基于连接键分别对两个表进行排序,然后再进行join连接。Mapper将特定键值的所有行发送给同一个Reducer。例如,假如表A有id为1,2,3,4,5五个值,而表B有id为1,2,3,4四个值。当我们有如下查询语句时:select A.ID FROM A  JOIN B ON A.ID=B.ID.假设在这个查询中id=1的数据是倾斜的,那么当其他Mapper发送给Reducer的数据都完成后,而id=1对应的Reducer则需要很长时间才能完成,这将拖累整个查询的效率。

配置优化倾斜连接的相关属性如下:

 

<property>
    <name>hive.optimize.skewjoin</name>
    <value>true</value>
</property>

<property>
    <name>hive.skewjoin.key</name>
    <value>100000</value>
</property>

<property>
    <name>hive.skewjoin.mapjoin.map.tasks</name>
    <value>20000</value>
</property>
<property>
    <name>hive.skewjoin.mapjoin.min.split</name>
    <value>33556872</value>
</property>

参数说明:
    hive.optimize.skewjoin:是否为join中的倾斜键创建单独的执行计划。它基于存储在元数据中的倾斜键。在编译时,Hive为倾斜键和其他键值生成各自的查询计划。
    hive.skewjoin.key:决定如何确定连接中的倾斜键。在连接操作中,如果同一键值所对应的数据行数超过该参数值,则认为该键是一个倾斜连接键。
    hive.skewjoin.mapjoin.map.tasks:指定倾斜连接中,用于Map连接作业的任务数。该参数应该与hive.skewjoin.mapjoin.min.split一起使用,用来执行粒度的控制。
    hive.skewjoin.mapjoin.min.split:通过指定最小split的大小,确定map连接作业的任务数。该参数应该与>hive.skewjoin.mapjoin.map.tasks一起使用,执行粒度的控制。
    
 

<3>桶map连接

  如果连接中使用的表是按特定列分桶的,可以开启桶Map连接来提高性能。

<property>
    <name>hive.optimize.bucketmapjoin</name>
    <value>true</value>
</property>

<property>
    <name>hive.optimize.bucketmapjoin.sortedmerge</name>
    <value>true</value>
</property>

参数说明:
    hive.optimize.bucketmapjoin:是否尝试桶Map连接。
    hive.optimize.bucketmapjoin.sortedmerge:是否尝试在桶map连接中使用归并扫描。
  

3.避免使用order by全局排序

   hive中使用order by排序只会用一个reducer进行排序,以达到全局排序。对于大数据集来说,这种做法是相当耗费时间。我们可以使用sort by 子句为每个reducer生成一个排好序的文件。如果需要控制一个特定的数据行流向哪个reducer,可以使用distribute by 子句,如:

select id,name,class from class_data  distribute by class sort by id desc;

4.优化limit操作

    默认时limit操作是执行整个查询,然后返回有一定限定的行。在某些情况下,这种处理方式比较浪费,我们可以通过设置下面的属性来避免此行为。

<property>
     <name>hive.limit.optimize.enable</name>
     <value>true</value>
</property>

<property>
     <name>hive.limit.row.max.size</name>
     <value>100000</value>
</property>

<property>
     <name>hive.limit.optimize.limit.file</name>
     <value>10</value>
</property>

<property>
     <name>hive.limit.optimize.fetch.max</name>
     <value>30000</value>
</property>

参数说明:
   hive.limit.optimize.enable:是否启用limit优化。当使用limit语句时,对源数据进行抽样。
   hive.limit.row.max.size:在使用limit做数据的子集查询时,保证最小的行数。
   hive.limit.optimize.limit.file:在使用limit做数据子查询时,采样的最大文件数。
   hive.limit.optimize.fetch.max:使用简单limit数据抽样时,允许的最大行数

 5.启用Tez执行引擎

    使用Tez执行引擎代替传统的MapReduce引擎会大幅提升hive的查询性能。配置Tez执行引擎如下:

<property>
  <name>hive.execution.engine</name>
  <value>tez</value>
</property>

6.启用并行执行

每个hiveQL都被转换成一个或多个阶段,可能是一个MapReduce阶段,采样阶段,归并阶段等。默认情况下hive在任意时刻只执行其中的一个阶段。如果组成一个特定作业的多个执行阶段是彼此独立的,那么它们可以并行执行。从而加快作业执行速度。通过配置以下选项开启并行执行。

<property>
    <name>hive.exec.parallel</name>
    <value>true</value>
</property>
<property>
    <name>hive.exec.parallel.thread.number</name>
    <value>5</value>
</property>

参数说明:
    hive.exec.parallel:是否并行执行作业
    hive.exec.parallel.thread.number:最多可以并行执行多少个作业数。

7.启用MapReduce严格模式:

hive提供一个严格的模式,可以防止用户执行那些可能产生负面影响的查询。通过设置下面的属性启用MapReduce严格模式。

<property>
    <name>hive.mapred.mode</name>
    <value>strict</value>
</property>

注意:
  此模式下禁止3种类型的查询:
      1.对于分区表,where子句不包含分区字段过滤条件的查询语句不允许执行。
      2.对于使用order by子句的查询,要求必须使用limit子句,否则不允许执行
      3.限制笛卡尔积查询。

 8.使用单一reduce执行多个Group by

    通过为group by 开启单一reduce任务属性,可以将一个查询中的多个group by操作联合在一起发送给单一MapReduce作业。

<property>
    <name>hive.multigroupby.singlereducer</name>
    <value>true</value>
</property>

9.使用ORC文件格式

    hive的orc文件格式可以有效提升hive查询性能。以下是一个hive不同文件格式大小的对比图:

10.使用向量化查询

  通过查询执行向量化,使hive从单行处理数据改为批量处理方式,具体来说是一次处理1024行而不是原来的每次只处理一行,这大大提升了指令流水线和缓存利用率,从而提高了表扫描、聚合、过滤和连接等操作的性能。通过以下配置启用向量化:

<property>
    <name>hive.vectorized.execution.enabled</name>
    <value>true</value>
</property>

<property>
    <name>hive.vectorized.execution.reduce.enabled</name>
    <value>true</value>
</property>

<property>
    <name>hive.vectorized.execution.reduce.groupby.enabled</name>
    <value>true</value>
</property>


参数说明如下:
    hive.vectorized.execution.enabled:如果该标志设置为true, 则开启查询执行的向量模式,默认值为false.
    hive.vectorized.execution.reduce.enabled:如果该标志为true,则开启查询执行reduce端的向量模式,默认值为true
    hive.vectorized.execution.reduce.groupby.enabled:如果该标志为true,则开启查询执行reduce端的group by操作的向量模式,默认值为true.

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值