Hive企业级性能优化(好文建议收藏)


Hive做为大数据平台举足轻重的框架,以其稳定性和简单易用性也成为当前构建企业级数据仓库时使用最多的框架之一。sql

可是若是咱们只局限于会使用Hive,而不考虑性能问题,就难搭建出一个完美的数仓,因此Hive性能调优是咱们大数据从业者必须掌握的技能。本文将给你们讲解Hive性能调优的一些方法及技巧。数据库

本文首发于公众号:五分钟学大数据

Hive性能问题排查的方式

当咱们发现一条SQL语句执行时间过长或者不合理时,咱们就要考虑对SQL进行优化,优化首先得进行问题排查,那么咱们能够经过哪些方式进行排查呢。性能优化

常用关系型数据库的同窗可能知道关系型数据库的优化的诀窍-看执行计划。 如Oracle数据库,它有多种类型的执行计划,经过多种执行计划的配合使用,能够看到根据统计信息推演的执行计划,即Oracle推断出来的未真正运行的执行计划;还能够看到实际执行任务的执行计划;可以观察到从数据读取到最终呈现的主要过程和中间的量化数据。能够说,在Oracle开发领域,掌握合适的环节,选用不一样的执行计划,SQL调优就不是一件难事。服务器

Hive中也有执行计划,可是Hive的执行计划都是预测的,这点不像Oracle和SQL Server有真实的计划,能够看到每一个阶段的处理数据、消耗的资源和处理的时间等量化数据。Hive提供的执行计划没有这些数据,这意味着虽然Hive的使用者知道整个SQL的执行逻辑,可是各阶段耗用的资源情况和整个SQL的执行瓶颈在哪里是不清楚的网络

想要知道HiveSQL全部阶段的运行信息,能够查看YARN提供的日志。查看日志的连接,能够在每一个做业执行后,在控制台打印的信息中找到。以下图所示:数据结构

Hive提供的执行计划目前能够查看的信息有如下几种并发

  1. 查看执行计划的基本信息,即explain;
  2. 查看执行计划的扩展信息,即explain extended;
  3. 查看SQL数据输入依赖的信息,即explain dependency;
  4. 查看SQL操做相关权限的信息,即explain authorization;
  5. 查看SQL的向量化描述信息,即explain vectorization。

在查询语句的SQL前面加上关键字explain是查看执行计划的基本方法。 用explain打开的执行计划包含如下两部分:框架

  • 做业的依赖关系图,即STAGE DEPENDENCIES;
  • 每一个做业的详细信息,即STAGE PLANS。

Hive中的explain执行计划详解可看我以前写的这篇文章jvm

Hive底层原理:explain执行计划详解分布式

注:使用explain查看执行计划是Hive性能调优中很是重要的一种方式,请务必掌握!

总结:Hive对SQL语句性能问题排查的方式

  1. 使用explain查看执行计划;
  2. 查看YARN提供的日志。

Hive性能调优的方式

为何都说性能优化这项工做是比较难的,由于一项技术的优化,必然是一项综合性的工做,它是多门技术的结合。咱们若是只局限于一种技术,那么确定作很差优化的。

下面将从多个彻底不一样的角度来介绍Hive优化的多样性,咱们先来一块儿感觉下。

1. SQL语句优化

SQL语句优化涉及到的内容太多,因篇幅有限,不能一一介绍到,因此就拿几个典型举例,让你们学到这种思想,之后遇到相似调优问题能够往这几个方面多思考下。

1. union all

insert into table stu partition(tp) 
select s_age,max(s_birth) stat,'max' tp 
from stu_ori
group by s_age

union all

insert into table stu partition(tp) 
select s_age,min(s_birth) stat,'min' tp 
from stu_ori
group by s_age;

咱们简单分析上面的SQl语句,就是将每一个年龄的最大和最小的生日获取出来放到同一张表中,union all 先后的两个语句都是对同一张表按照s_age进行分组,而后分别取最大值和最小值。对同一张表相同的字段进行两次分组,这形成了极大浪费,咱们能不能改造下呢,固然是能够的,为你们介绍一个语法:
from ... insert into ... ,这个语法将from前置,做用就是使用一张表,能够进行屡次插入操做:

--开启动态分区 
set hive.exec.dynamic.partition=true; 
set hive.exec.dynamic.partition.mode=nonstrict; 

from stu_ori 

insert into table stu partition(tp) 
select s_age,max(s_birth) stat,'max' tp 
group by s_age

insert into table stu partition(tp) 
select s_age,min(s_birth) stat,'min' tp 
group by s_age;

上面的SQL就能够对stu_ori表的s_age字段分组一次而进行两次不一样的插入操做。

这个例子告诉咱们必定要多了解SQL语句,若是咱们不知道这种语法,必定不会想到这种方式的

2. distinct

先看一个SQL,去重计数:

select count(1) 
from( 
  select s_age 
  from stu 
  group by s_age 
) b;

这是简单统计年龄的枚举值个数,为何不用distinct?

select count(distinct s_age) 
from stu;

有人说由于在数据量特别大的状况下使用第一种方式可以有效避免Reduce端的数据倾斜,可是事实如此吗?

咱们先无论数据量特别大这个问题,就当前的业务和环境下使用distinct必定会比上面那种子查询的方式效率高。缘由有如下几点:

  1. 上面进行去重的字段是年龄字段,要知道年龄的枚举值是很是有限的,就算计算1岁到100岁之间的年龄,s_age的最大枚举值才是100,若是转化成MapReduce来解释的话,在Map阶段,每一个Map会对s_age去重。因为s_age枚举值有限,于是每一个Map获得的s_age也有限,最终获得reduce的数据量也就是map数量*s_age枚举值的个数。
  2. distinct的命令会在内存中构建一个hashtable,查找去重的时间复杂度是O(1);group by在不一样版本间变更比较大,有的版本会用构建hashtable的形式去重,有的版本会经过排序的方式, 排序最优时间复杂度没法到O(1)。另外,第一种方式(group by)去重会转化为两个任务,会消耗更多的磁盘网络I/O资源。
  3. 最新的Hive 3.0中新增了 count(distinct ) 优化,经过配置 hive.optimize.countdistinct,即便真的出现数据倾斜也能够自动优化,自动改变SQL执行的逻辑。
  4. 第二种方式(distinct)比第一种方式(group by)代码简洁,表达的意思简单明了,若是没有特殊的问题,代码简洁就是优!

这个例子告诉咱们,有时候咱们不要过分优化,调优讲究适时调优,过早进行调优有可能作的是无用功甚至产生负效应,在调优上投入的工做成本和回报不成正比。调优须要遵循必定的原则

2. 数据格式优化

Hive提供了多种数据存储组织格式,不一样格式对程序的运行效率也会有极大的影响。

Hive提供的格式有TEXT、SequenceFile、RCFile、ORC和Parquet等。

SequenceFile是一个二进制key/value对结构的平面文件,在早期的Hadoop平台上被普遍用于MapReduce输出/输出格式,以及做为数据存储格式。

Parquet是一种列式数据存储格式,能够兼容多种计算引擎,如MapRedcue和Spark等,对多层嵌套的数据结构提供了良好的性能支持,是目前Hive生产环境中数据存储的主流选择之一。

ORC优化是对RCFile的一种优化,它提供了一种高效的方式来存储Hive数据,同时也可以提升Hive的读取、写入和处理数据的性能,可以兼容多种计算引擎。事实上,在实际的生产环境中,ORC已经成为了Hive在数据存储上的主流选择之一。

咱们使用一样数据及SQL语句,只是数据存储格式不一样,获得以下执行时长:

数据格式 CPU时间 用户等待耗时
TextFile 33分 171秒
SequenceFile 38分 162秒
Parquet 2分22秒 50秒
ORC 1分52秒 56秒
注: CPU时间:表示运行程序所占用服务器CPU资源的时间。
*用户等待耗时*:记录的是用户从提交做业到返回结果期间用户等待的全部时间。

查询TextFile类型的数据表耗时33分钟, 查询ORC类型的表耗时1分52秒,时间得以极大缩短,可见不一样的数据存储格式也能给HiveSQL性能带来极大的影响。

3. 小文件过多优化

小文件若是过多,对 hive 来讲,在进行查询时,每一个小文件都会当成一个块,启动一个Map任务来完成,而一个Map任务启动和初始化的时间远远大于逻辑处理的时间,就会形成很大的资源浪费。并且,同时可执行的Map数量是受限的。

因此咱们有必要对小文件过多进行优化,关于小文件过多的解决的办法,我以前专门写了一篇文章讲解,具体可查看:

解决hive小文件过多问题

4. 并行执行优化

Hive会将一个查询转化成一个或者多个阶段。这样的阶段能够是MapReduce阶段、抽样阶段、合并阶段、limit阶段。或者Hive执行过程当中可能须要的其余阶段。默认状况下,Hive一次只会执行一个阶段。不过,某个特定的job可能包含众多的阶段,而这些阶段可能并不是彻底互相依赖的,也就是说有些阶段是能够并行执行的,这样可能使得整个job的执行时间缩短。若是有更多的阶段能够并行执行,那么job可能就越快完成。

经过设置参数hive.exec.parallel值为true,就能够开启并发执行。在共享集群中,须要注意下,若是job中并行阶段增多,那么集群利用率就会增长。

set hive.exec.parallel=true; //打开任务并行执行
set hive.exec.parallel.thread.number=16; //同一个sql容许最大并行度,默认为8。

固然得是在系统资源比较空闲的时候才有优点,不然没资源,并行也起不来。

5. JVM优化

JVM重用是Hadoop调优参数的内容,其对Hive的性能具备很是大的影响,特别是对于很难避免小文件的场景或task特别多的场景,这类场景大多数执行时间都很短。

Hadoop的默认配置一般是使用派生JVM来执行map和Reduce任务的。这时JVM的启动过程可能会形成至关大的开销,尤为是执行的job包含有成百上千task任务的状况。JVM重用可使得JVM实例在同一个job中从新使用N次。N的值能够在Hadoop的mapred-site.xml文件中进行配置。一般在10-20之间,具体多少须要根据具体业务场景测试得出。

<property>
  <name>mapreduce.job.jvm.numtasks</name>
  <value>10</value>
  <description>How many tasks to run per jvm. If set to -1, there is
  no limit. 
  </description>
</property>

咱们也能够在hive中设置

set  mapred.job.reuse.jvm.num.tasks=10; //这个设置来设置咱们的jvm重用

  
这个功能的缺点是,开启JVM重用将一直占用使用到的task插槽,以便进行重用,直到任务完成后才能释放。若是某个“不平衡的”job中有某几个reduce task执行的时间要比其余Reduce task消耗的时间多的多的话,那么保留的插槽就会一直空闲着却没法被其余的job使用,直到全部的task都结束了才会释放。

6. 推测执行优化

在分布式集群环境下,由于程序Bug(包括Hadoop自己的bug),负载不均衡或者资源分布不均等缘由,会形成同一个做业的多个任务之间运行速度不一致,有些任务的运行速度可能明显慢于其余任务(好比一个做业的某个任务进度只有50%,而其余全部任务已经运行完毕),则这些任务会拖慢做业的总体执行进度。为了不这种状况发生,Hadoop采用了推测执行(Speculative Execution)机制,它根据必定的法则推测出“拖后腿”的任务,并为这样的任务启动一个备份任务,让该任务与原始任务同时处理同一份数据,并最终选用最早成功运行完成任务的计算结果做为最终结果。

设置开启推测执行参数:Hadoop的mapred-site.xml文件中进行配置:

<property>
  <name>mapreduce.map.speculative</name>
  <value>true</value>
  <description>If true, then multiple instances of some map tasks 
               may be executed in parallel.</description>
</property>

<property>
  <name>mapreduce.reduce.speculative</name>
  <value>true</value>
  <description>If true, then multiple instances of some reduce tasks 
               may be executed in parallel.</description>
</property>

hive自己也提供了配置项来控制reduce-side的推测执行:

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

关于调优这些推测执行变量,还很难给一个具体的建议。若是用户对于运行时的误差很是敏感的话,那么能够将这些功能关闭掉。若是用户由于输入数据量很大而须要执行长时间的map或者Reduce task的话,那么启动推测执行形成的浪费是很是巨大大。


公众号【五分钟学大数据】,大数据领域原创技术号

最后

代码优化原则:

  • 理透需求原则,这是优化的根本;
  • 把握数据全链路原则,这是优化的脉络;
  • 坚持代码的简洁原则,这让优化更加简单;
  • 没有瓶颈时谈论优化,这是自寻烦恼。

相关文章
相关标签/搜索