hive 数组_Hive问题排查与调优思路

本文详细介绍了Hive调优的全过程,从新手角度出发,逐步理解执行计划和MapReduce原理。通过学习大数据分布式计算,分析YARN日志,以及运用SQL改写、Hint语法和配置参数调整等方法进行调优。同时,文章探讨了如何从执行计划、日志分析和实践经验中构建适合Hive的调优策略。
摘要由CSDN通过智能技术生成

将介绍Hive整体的调优过程,以及个人对于Hive调优过程中的一些思考,包括编码和调优的原则、Hive SQL的相关开发规范等,能够对Hive调优过程和调优工具有一个整体的感知。

在介绍Hive整体调优过程之前,先介绍两种截然不同的Hive调优思路。

第一种,从一个无经验的小白角度,谈谈对于Hive 调优过程的思考。这个角度偏向于问题驱动,也是技术人员在实际开发中获取新知识的一种方式。读者在阅读这部分内容时请思考小白的优化思路和方法存在哪些问题?是否需要进行改进?

第二种,站在从事大数据开发多年的老工角度,以他的视角来看如何归纳自己的调优方法。将从总结知识的角度来谈Hive 的优化。读者可以对照自己的调优方法,如果认为这些解决方法适合自己,也可以兼收并蓄。

2.1 小白推演Hive的优化方法

在刚接触Hive时只会套用PL-SQL和T-SQL的编码方式去编写HiveSQL程序,也会套用Oracle和MySQL调优的方法用于Hive调优。但Hive毕竟和关系型数据库不同,随着对其了解的增多,会发现两者调优方法的异同。这时需要遵循Hive 自身的特性,来构建一套属于Hive的调优方法

将介绍一个“小白”调优的过程,即从一个从没有接触过Hive 的新手小白,成长到能够熟练使用Hive,并能够利用相关工具解决日常工作中发生的问题的成长过程。

2.1.1 类比关系型数据库的调优

小白之前用过一段时间的Oracle等关系型数据库,并总结了关系型数据库优化的诀窍——看执行计划。Oracle是一个成熟的产品,当要调优时需要掌握两类必备的工具:执行计划和各种类型的系统报表Oracle能提供多种类型的报表,最常用的是AWR报表,但Hive没有这种类型的报表,因此小白放弃了这点

Oracle有多种类型的执行计划,通过多种执行计划的配合使用,可以看到根据统计信息推演的执行计划,即Oracle推断出来的未真正运行的执行计划;还可以看到实际执行任务的执行计划;能够观察到从数据读取到最终呈现的主要过程和中间的量化数据。

可以说,在Oracle开发领域,掌握合适的环节,选用不同的执行计划,SQL调优就不是一件难事

如图2.1所示

是Oracle两个表t1和t2做join的预估执行计划图。

3bc81a6c454f7e1f3db2588fd87e5b87.png

图2.1 Oracle执行计划

在执行计划中,可以看到这段代码在执行过程中所做的操作(Operation),每个逻辑涉及的两个表在做连接时各个阶段的数据行(Rows)、数据量(Bytes)、耗时(Time)和执行成本(Cost)。其中,Cost是Oracle基于成本评估模型计算出来的值,值越大表示成本越大。在统计信息里面,可以看到有递归调用次数(recursive calls)、获取的数据块(db block gets)、一致性读次数(consistent gets)、物理读(physicalreads)等信息。通过这些信息,可以直接了解到SQL执行的各个阶段的数据参数,用于去发现定位和调优

小白觉得Hive 也是数据库,用执行计划也能解决大部分问题。带着这种想法,小白在忍受不了缓慢的HiveSQL时,第一次打开了执行计划见下面的案例2.1。

【案例2.1】 使用explain查看HiveSQL的执行计划。e0031b055e6bedbd219d9c525dcafe3e.png

当小白初次看到这个执行计划时一脸迷茫,经过查阅Hive 的官网资料才慢慢明白,上面的信息描述的是计算引擎的执行逻辑。Hive架设在Hadoop集群上,如果计算引擎使用的是MapReduce, HiveSQL默认最后会解析并转化成MapReduce算子,如果是架设在Spark集群上,则会转化成Spark算子,去执行计算。小白意识到,要想对Hive的优化有进一步理解,关键是要知道计算引擎。

扩展:不管执行引擎是MapReduce还是Spark,它们的执行计划都大同小异,可以通过以下方式查看案例2.2的spark执行计划。

【案例2.2】 查看使用spark计算引擎的执行计划。

078211b908c0f92ab62a3767ab1310f8.png

2.1.2 学习大数据分布式计算的基本原理

学习计算引擎工作的方式,就是先去使用它。先编写一个简单的例子,并将这个例子运行起来,对基本运行过程有个简单的认识,之后再去深究背后的原理,这样的学习方式,效果会事半功倍

在所有的分布式计算引擎中,MapReduce是最为简单的计算引擎,小白决定通过学些MapReduce引擎,来打开自己对分布式计算认知的第一步。MapReduce 提供了两个开发者编写业务逻辑的编程接口 Mapper 和Reducer,这两个接口已经定义好了输入和输出的格式,开发者只需要去编写每个接口对应的方法,对于学过编程有一定基础的读者来说都是较为简单的工作。MapReduce 对于习惯写 SQL 的读者毕竟是新东西,要了解它,最快的方式就是看例子,并尝试构建一个案例。于是小白打开Hadoop官网,并学习Hadoop入门案例wordcount,即案例2.3。wordcount案例指的是输入一段文本,统计文本中各个单词个数的程序案例。下面是一个wordcount案例。输入:

4223028a771e3f78683984fa0c6efc90.png

输出:

97a516e609ff47374d976f4678661dc4.png

其中,value中的数字代表单词个数。上面的例子程序处理过程可以用案例2.3来表示。

【案例2.3】 经典的wordcount案例。 

 小白看了几遍wordcount代码并动手临摹了一遍后,就尝试用MapReduce来写以前用SQL 写的业务逻辑,比如-PV 统计、UV 统计。之后小白总结并画了下面一个wordcount在MapReduce中数据的变换过程

如图所示。

ee5f2a19a885b379973d74efc5c73a08.png

图2.2中主要演示了3个阶段。

阶段1:file到Mapper阶段在file1中将一行行的文本转化成键-值对的形式输入到Mapper 中,其中键为行所在位置的偏移量(offset),值为文本内容。

在Mapper 的map函数中输入的值,被切分成一个个单词并输出,输出也是以键-值对的形式输出的,其中,键是文本中的一个个单词,值是固定值1

阶段2:Mapper到Combiner阶段Combiner将汇集本地多个Mapper输出的结果并转化为键-值对的形式,输入键是Mapper 输出键,输入值是由Map 输出键相同的输出值组成的一个数组。例如,在node server1中,mapper1和mapper2各出现一次word1单词,在combiner的输入表现形式键为word1,值为数组[1,1]。Combiner的输出和Mapper输出格式一样,key 值就是单词,value 则是本地 mapper 所有单词个数的总和。例如,word1的值就会以2的形式输出。

阶段3:Combiner到Reducer阶段Reducer阶段所做的事情和Combiner一样,输入和输出都和Combiner保持一致,事实上,Reducer的代码可以直接使用在Combiner上,唯一不同的是Reducer接受的数据来自于远端Combiner的输出。因此,在配置作业信息的时候,可以直接使用job.setCombinerClass(IntSumReducer.class)来启用Combiner计算过程。这一点和启用Reduce计算过程中设置方式:job.setReducerClass(IntSumReducer.class)是一样的

55a5150016e9ce135740f6df1325bbdd.png

图2.2 WordCount数据变化图

小白整理完图2.2,觉得对MapReduce的数据处理逻辑有了清楚认识,也开始理解执行计划中的关键词及其表示的含义,例如执行计划中出现的Map Operator Tree和Reduce Operator Tree;也能慢慢将SQL转化为MapReduce,例如SQL执行计划中的Select Operator就是对列的投影操作,转化成MapReduce 算子就是对一行的数据按一定的列分割符进行分割并取出该列。

总结,其实不仅仅是MapReduce在数据处理时将所有的数据简化成业务无关的键-值对模式,大部分的大数据数计算引擎在底层实现上也是如此,如Spark、Tez和Storm在进行数据处理时先将计算发往数据所在的节点,将数据以键-值对作为输入,在本地处理后再以键-值对的形式发往远端的节点,这个过程通用叫法为Shuffle远端的节点将接收的数据组织成键-值对的形式作为输入,处理后的数据,最终也以键-值对的形式输出。这些都会体现在执行计划上。

2.1.3 学习使用YARN提供的日志

通过对MapReduce的学习,小白逐渐看懂了执行计划所表示的含义,只是Hive的执行计划和Oracle不一样,里面没有相关的具体量化数据,如Rows和Cost等在关系型数据库中,通过执行计划可以看到每个阶段的处理数据、消耗的资源和处理的时间等量化数据Hive提供的执行计划没有这些数据,这意味着虽然Hive的使用者知道整个SQL的执行逻辑,但是各阶段耗用的资源状况和整个SQL 的执行瓶颈在哪里是不清楚的于是小白去求助于组内经验颇丰的老工。老工提到,想要知道HiveSQL 所有阶段的运行信息,可以查看日志。查看日志的链接,可以在每个作业执行后,在控制台打印的信息中找到。于是小白尝试执行一个SQL,得到如图2.3所示的信息。

d2c96891e3e637f2861918a313b8fa85.png

图2.3 HiveSQL执行结果

范例在图2.3中,Tracking URL就是我们需要的日志链接,单击该链接,将得到如图2.4所示的页面。

fcdd44ba5634cba5eacd8b960448e925.png

图2.4 Tracking URL的链接页面

小白从页面的信息可知,该页面反应了SQL运行的整体概况,于是尝试继续挖掘这个页面更多的信息。单击左边Job 下的Counters 链接,可以看到熟悉的信息,如图2.5所示。

4424a171492d9fe4bac20eb739b6df7b.png

图2.5 MapReduce的Counters信息

图2.5就是描述MapReduce作业在各个阶段的量化数据结合之前所了解的MapReduce基本原理,小白也能看懂几个关键词。例如,Map input records表示Map阶段输入的记录数,Map output bytes表示输出数据的字节数,Map outrecords表示Map阶段输出的记录数,Reduce input Records表示输入的字节数等。通过这些关键词,可以看到一个作业在运行中具体的、可以量化的数据描述。上面的信息在调优的时候会经常用到,在后续的章节中我们会详细介绍上面各个关键词的含义。

2.1.4 干预SQL的运行方式

在调优时,我们会经常性干预SQL 的运行过程,以便选择一种计算引擎运行效率最佳的SQL。那么在Hive中通过什么方式能够干预SQL的执行来达到最终的调优呢?小白按过往写PL-SQL和T-SQL的经验,总结了3条经验:

● 通过改写SQL,实现对计算引擎执行过程的干预;

● 通过SQL-hint语法,实现对计算引擎执行过程的干预;

● 通过数据库开放的一些配置开关,实现对计算引擎的干预。

1.通过改写SQL实现对计算引擎执行过程的干预

通过改写SQL实现对MapReduce执行过程的调优,这种方式需要对HiveSQL的语法、用户有比较详细的了解。于是小白先通读了HiveSQL 的用户手册,并开始学习各种能够提高Hive的SQL写法,比如下面是小白收集的案例2.4和案例2.5。

【案例2.4】 使用grouping sets代替union的SQL优化。

decf1d1d7a9c4948b14bb5efe9421dd9.png

【案例2.5】 分解count(distinct)的SQL优化。

d3dc989b341af8ec5943a66cbdd02f40.png

小白收集了一堆在网上帖子里看到的糟糕的SQL 优化写法,并尝试将这些规则进行记录。收集这些规则,如果遇到类似的代码,可以直接进行套用。

2.通过SQL-Hint语法实现对计算引擎执行过程的干预在以往的关系数据库编程中,Hint 也是一个比较常用的使用方式,通过Hint 可以强制干预SQL的运行逻辑比如Oracle,在大数据量的表连接中可以用hash join和merge sort join优化nested loop join,以期提高多表接连的速度。因此,小白觉得Hive的Hint命令也是丰富自己调优技能的方法之一。于是开始翻阅Hive的wiki文档,发现Hive对Hint命令也支持,最常见的有下面两种Hint,见案例2.6和案例2.7。

【案例2.6】 使用MapJoin Hint的SQL。

8d09911c9868b8be527ea53fafaf5e35.png

【案例2.7】 使用STREAMTABLE的SQL。

8f6e7c2e7ecb4d1ea48c16acf4856642.png

Hint语法Hive支持有限,但是小白在实际工作中确实觉得这些命令对性能提升巨大。于是Hint命令成为了小白在开发中经常使用的方法。

3.通过数据库开放的一些配置开关,来实现对计算引擎的干预在关系型数据库中,通过数据库提供的配置开关可以实现一部分的性能调优。比如,一次性要写入大量的数据,为了提高写入效率,可以暂时关闭WAL日志,可以适当开启并行等操作。在Hive的wiki里小白也发现了相关的配置选项。于是也收集了一些案例。

【案例2.8】 通过配置,实现对计算引擎运行过程的干预。

5e50e85be788c2a1c6f57ce0279b4b3b.png

开启hive.vectorized.execution.enabled操作,默认是关闭状态,将一个普通的查询转化为向量化查询执行是一个Hive 特性它大大减少了扫描、过滤器、聚合和连接等典型查询操作的CPU 使用标准查询执行系统一次处理一行。矢量化查询执行可以一次性处理1024行的数据块,以减少底层操作系统处理数据时的指令和上下文切换。在支持向量化查询的数据块中,每个列都存储为一个向量(原始数据类型的数组)。像算术和比较这样的简单操作,是通过在一个紧凑的循环中快速迭代向量来完成的,在循环中没有或很少有函数调用或条件判断分支。这些循环以一种简化的方式编译,使用相对较少的指令,通过有效地使用处理器管道和缓存内存,在更少的时钟周期内完成每条指令。简单地说就是,将单条的数据处理,转化为一次1万条数据的批量处理,优化了底层硬件资源的利用率。除了开启向量化查询操作,还可以开启并行执行的操作,如案例2.9。

【案例2.9】 开启并行执行。

b2a70dcfb7c438acb7ce31553db8c14d.png

通过开启并行,原来案例2.9的3个作业(作业1是计算max,作业2是计算min,作业3是计算并集)串行执行变为并行执行,即原来的1→2→3,变为(1,2)→3,其中, 1、2同时计算。

扩展:并行执行是大数据分布式计算的核心概念。SQL开发者提交的每个SQL都会尽量被分解成各个可以并行的任务去执行。

小白将自己以往对关系型数据库的调优方法迁移到Hive SQL的调优学习中。先以执行计划作为切入点,但他发现要看懂执行计划,关键还是要懂MapReduce 原理。于是小白研究了最基本的MapReduce 代码案例。为了较好地理解MapReduce,他动手“临摹”了一遍MapReduce案例,并尝试用MapReduce程序去写几个常见的统计程序,如统计某个应用程序的PV、UV。小白通过对MapReduce的学习,能看懂执行计划,但执行计划仅能提供SQL的执行逻辑,却没有提供每个过程的一些量化统计信息,这对于调优的帮助有限。于是小白去请教老工,知道计算引擎基于YARN调度,可以通过YARN提供的工具查看Job日志。查看YARN Job日志可以知晓MapReduce整个过程的量化数据信息,可以较好地定位整个程序的瓶颈位置。定位到出现瓶颈的位置后,小白尝试使用优化“三板斧”:

利用别人已有的经验来改写SQL;

给SQL语句用上Hint的语法;

使用数据库开放的配置参数。

以上便是小白所经历的调优过程这个过程符合实际开发中新手不断遇到问题而深入挖掘的过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值