大数据技术框架中,hive组件作为数仓工程师必不可缺少的计算框架组件。本篇文章是hive性能调优详解系列之第三篇hive语法层面调优。
上两篇分别为
hive 建设表层面调优
hive 语法和参数层面调优
更多内容请关注哔哩:老姜的数据江湖,微信公众号同步;
Hive的某些SQL语句需要转换成MapReduce的操作,某些SQL语句就不需要转换成MapReduce操作,例如:
1.只是select *的时候
2.where条件针对分区字段进行筛选过滤时
3.带有limit分支语句时
Hive从HDFS中读取有两种方式:启用MapReduce读取和直接抓取。
直接抓取数据比MapReduce方式读取数据要快的多,但是只有少数操作可以使用直接抓取方式。
可以通过hive. fetch. task, conversion参数来配置在什么情况下采用直接抓取方式:
minimal:只有select *、在分区字段上where过滤、有limit这三种场景下才启用直接抓取方 式。
more:在select、where筛选「limit时,都启用直接抓取方式。
查看Hive的抓取策略:
##查看 set hive.fetch.task.conversion;
设置Hive的抓取策略:
##默认more set hive.fetch.task.conversion=more;
请看hive-default.xml中关于这个参数的解释:
<property>
<name>hive.fetch.task.conversionname>
<value>morevalue>
<description>
Expects one of [none, mi nimal, more].
Some select queri es can be converted to single FETCH task minimizing latency.
Currently the query should be si ngle sourced not havi ng any subquery and should not have
any aggregations or di sti ncts (whi ch i ncurs RS), lateral vi ews and
joi ns.
0. none : di sable hive.fetch.task.conversion
1.minimal : select star, filter on partition columns, limit only
2.more : SELECT, FILTER, LIMIT only (support TABLESAMPLE and vi rtual
columns)
descri ption>
property>
<property>
<name>hive.fetch.task.conversion.thresholdname>
<value>1073741824value>
<descri pti on>
input threshold for applying hive.fetch.task.conversion, if target table is native, input 1ength
is calculated by summation of file 1engths. if it's not native, storage handler for the table
can optionally implement
org.apache, hadoop. hive, ql. metadata. inputEstimator iinterface.
descri ption>
property>
Hive在集群上查询时,默认是在集群上多台机器上运行,需要多个机器进行协调运行,这种方式很好的解决了大数据量的查询问题。但是在Hive查询处理的数据量比较小的时候,其实没有必要启动分布式模式去执行,因为以分布式方式执行设计到跨网络传输、多节点协调等,并且消耗资源。对于小数据 集,可以通过本地模式,在单台机器上处理所有任务,执行时间明显被缩短。
启动本地模式涉及到三个参数:
##打开hive自动判断是否启动本地模式的开关 set hive.exec.mode.local.auto=true;
##map任务晝專大值,*启用本地模式的task最大皋数 set hive.exec.mode.1ocal.auto.input.files.max=4;
##map输入文件最大大小,不启动本地模式的最大输入文件大小 set hive.exec.mode.1ocal.auto.inputbytes.max=134217728;
Hive语句最终会转换为一系的MapReduce任务,每一个MapReduce任务是由一系的MapTask 和ReduceTask组成的,默认情况下,MapReduce中一个MapTask或者ReduceTask就会启动一个 JVM进程,一个Task执行完毕后,JVM进程就会退出。这样如果任务花费时间很短,又要多次启动 JVM的情况下,JVM的启动时间会变成一个比较大的消耗,这时,可以通过重用JVM来解决。
set mapred.job.reuse.jvm.num.tasks=5;
JVM也是有缺点的,开启JVM重用会一直占用使用到的task的插槽,以便进行重用,直到任务完成后才会释放。如果某个不平衡的job中有几个reduce task执行的时间要比其他的reduce task消耗的时间要多得多的话,那么保留的插槽就会一直空闲却无法被其他的job使用,直到所有的task都结束了才 会释放。
根据经验,一般来说可以使用一个cpu core启动一个JVM,假如服务器有16个cpu core,但是这个节点,可能会启动32个mapTask,完全可以考虑:启动一个JVM,执行两个Task
有的查询语句,Hive会将其转化为一个或多个阶段,包括:MapReduce阶段、抽样阶段、合并阶段、 limit阶段等。默认情况下,一次只执行一个阶段。但是,如果某些阶段不是互相依赖,是可以并行执行的。多阶段并行是比较耗系统资源的。
—个Hive SQL语句可能会转为多个MapReduce Job,每一个job就是一个stage,这些Job顺序执行,这个在client的运行日志中也可以看到。但是有时候这些任务之间并不是是相互依赖的,如果集群资源允许的话,可以让多个并不相互依赖stage并发执行,这样就节约了时间,提高了执行速度,但是如果集群资源溃泛时,启用并行化反倒是会导致各个Job相互抢占资源而导致整体执行性能的下降。启用并行化:
##可以开启并发执行。
set hive.exec.parallei=true;
##同一个sql允许最大并行度,默认为8。
set hive.exec.paral1 el.thread.number=16;
在分布式集群环境下,因为程序Bug (包括Hadoop本身的bug),负载不均衡或者资源分布不均等原因,会造成同一个作业的多个任务之间运行速度不一致,有些任务的运行速度可能明显慢于其他任务
(比如一个作业的某个任务进度只有50%,而其他所有任务已经运行完毕),则这些任务会拖慢作业的整体执行进度。为了避免这种情况发生,Hadoop采用了推测执行(Speculative Execution)机制,它根据一定的法则推测出"拖后腿"的任务,并为这样的任务启动一个备份任务,让该任务与原始任务同时处理同一份数据,并最终选用最先成功运行完成任务的计算结果作为最终结果。
#启动mapper阶段的推测执行机制 set mapreduce.map.speculative=true;
#启动reducer阶段的推测执行机制 set mapreduce.reduce.speculative=true;
建议:
如果用户对于运行时的偏差非常敏感的话,那么可以将这些功能关闭掉。如果用户因为输入数据量很大而需要执行长时间的MapTask或者ReduceTask的话,那么启动推测执行造成的浪费是非常巨大大。
设置开启推测执行参数:Hadoop的mapred-site.xml文件中进行配置
<property>
<name>mapreduce.map.speculativename>
<value>truevalue>
<description>lf true, then multiple i nstances of some map tasks may be executed i n parallel.description>
property>
<property>
<name>mapreduce.reduce.speculati vename>
<value>truevalue>
<descri pti on>lf true, then multi ple i nstances of some reduce tasks may be executed in parallel.description>
property>
Hive本身也提供了配置项来控制reduce-side的推测执行
<property>
<name>hive.mapped.reduce.tasks.speculative.executi onname>
<value>truevalue>
<description>whether speculative execution for reducers should be turned on. description>
property>
关于调优这些推测执行变量,还很难给一个具体的建议。如果用户对于运行时的偏差非常敏感的话,那么可以将这些功能关闭掉。如果用户因为输入数据量很大而需要执行长时间的mapTask或者 reduceTask的话,那么启动推测执行造成的浪费是非常巨大。
所谓严格模式,就是强制不允许用户执行有风险的HiveQL语句,一旦执行会直接报失败。在Hive中为了提高SQL语句的执行效率,可以设置严格模式,充分利用Hive的某些特点。
##设置Hive的严格模式
set hive.map red.mode=strict;
set hive.exec.dynamic.partition.mode=nostrict;
注意:当设置严格模式之后,会有如下限制:
1.对于分区表,必须添加where对于分区字段的条件过滤 seiect * from student_ptn where age > 25
2.order by语句必须包含limit输出限制 seiect * from student order by age 1imit 100;
3.限制执行笛卡尔积的查询 select a., b. from a, b;
4.在hive的动态分区模式下,如果为严格模式,则必须需要一个分区列式静态分区