Hive 作为大数据平台无足轻重的框架,以其稳定性和简略易用性也成为以后构建企业级数据仓库时应用最多的框架之一。
然而如果咱们只局限于会应用 Hive,而不思考性能问题,就难搭建出一个完满的数仓,所以 Hive 性能调优是咱们大数据从业者必须把握的技能。本文将给大家解说 Hive 性能调优的一些办法及技巧。
本文首发于公众号:五分钟学大数据
Hive 性能问题排查的形式
当咱们发现一条 SQL 语句执行工夫过长或者不合理时,咱们就要思考对 SQL 进行优化,优化首先得进行问题排查,那么咱们能够通过哪些形式进行排查呢。
常常应用关系型数据库的同学可能晓得关系型数据库的优化的窍门 -看执行打算。如 Oracle 数据库,它有多种类型的执行打算,通过多种执行打算的配合应用,能够看到依据统计信息推演的执行打算,即 Oracle 推断进去的未真正运行的执行打算;还能够看到理论执行工作的执行打算;可能察看到从数据读取到最终出现的次要过程和两头的量化数据。能够说,在 Oracle 开发畛域,把握适合的环节,选用不同的执行打算,SQL 调优就不是一件难事。
Hive 中也有执行打算,然而 Hive 的执行打算都是预测的,这点不像 Oracle 和 SQL Server 有实在的打算,能够看到每个阶段的解决数据、耗费的资源和解决的工夫等量化数据。Hive 提供的执行打算没有这些数据,这意味着尽管 Hive 的使用者晓得整个 SQL 的执行逻辑,然而各阶段耗用的资源情况和整个 SQL 的执行瓶颈在哪里是不分明的。
想要晓得 HiveSQL 所有阶段的运行信息,能够查看YARN 提供的日志。查看日志的链接,能够在每个作业执行后,在控制台打印的信息中找到。如下图所示:
Hive 提供的执行打算目前能够查看的信息有以下几种:
- 查看执行打算的根本信息,即 explain;
- 查看执行打算的扩大信息,即 explain extended;
- 查看 SQL 数据输出依赖的信息,即 explain dependency;
- 查看 SQL 操作相干权限的信息,即 explain authorization;
- 查看 SQL 的向量化形容信息,即 explain vectorization。
在查问语句的 SQL 后面加上关键字 explain 是查看执行打算的根本办法。用 explain 关上的执行打算蕴含以下两局部:
- 作业的依赖关系图,即 STAGE DEPENDENCIES;
- 每个作业的详细信息,即 STAGE PLANS。
Hive 中的 explain 执行打算详解可看我之前写的这篇文章:
Hive 底层原理:explain 执行打算详解
注:应用 explain 查看执行打算是 Hive 性能调优中十分重要的一种形式,请务必把握!
总结:Hive 对 SQL 语句性能问题排查的形式:
- 应用 explain 查看执行打算;
- 查看 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 岁到 100 岁之间的年龄,s_age 的最大枚举值才是 100,如果转化成 MapReduce 来解释的话,在 Map 阶段,每个 Map 会对 s_age 去重。因为 s_age 枚举值无限,因此每个 Map 失去的 s_age 也无限,最终失去 reduce 的数据量也就是 map 数量 *s_age 枚举值的个数。
- distinct 的命令会在内存中构建一个 hashtable,查找去重的工夫复杂度是 O(1);group by 在不同版本间变动比拟大,有的版本会用构建 hashtable 的模式去重,有的版本会通过排序的形式,排序最优工夫复杂度无奈到 O(1)。另外,第一种形式 (group by) 去重会转化为两个工作,会耗费更多的磁盘网络 I / O 资源。
- 最新的 Hive 3.0 中新增了 count(distinct) 优化,通过配置
hive.optimize.countdistinct
,即便真的呈现数据歪斜也能够主动优化,主动扭转 SQL 执行的逻辑。 - 第二种形式 (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 的话,那么启动揣测执行造成的节约是十分微小大。
公众号【五分钟学大数据】,大数据畛域原创技术号
最初
代码优化准则:
- 理透需要准则,这是优化的基本;
- 把握数据全链路准则,这是优化的脉络;
- 保持代码的简洁准则,这让优化更加简略;
- 没有瓶颈时议论优化,这是自寻烦恼。