Hive常见的优化⽅式
⽂章⽬录
⼀、前⾔
Hive是基于Hadoop的⼀个数据仓库⼯具,可以将结构化的数据⽂件映射为⼀张表,并提供类SQL查询功能。
本质是:将HQL转化成MapReduce程序。此篇⽂章对于hive如何使⽤、如何配置及⼀些基础性的知识不做阐述;直⼊重点聊⼀聊如何通过常见的⼀些⼿段⽅法提⾼hive的性能、提⾼执⾏效率。
⼆、调优
1.替换执⾏引擎为tez
在我之前的⽂章中已经讲解了如何配置,
2.Fetch抓取
Fetch抓取是指,Hive中对某些情况的查询可以不必使⽤MapReduce计算。例如:SELECT * FROM tabl
e在这种情况下,Hive可以简单地读取table表对应的存储⽬录下的⽂件,然后输出查询结果到控制台。在plate⽂件中hive.version 默认是more,⽼版本hive默认是minimal,该属性修改为more以后,在全局查、字段查、limit查等都不⾛mapreduce。
<property>
<name>hive.version</name>
<value>more</value>
<description>
Expects one of [none, minimal, more].
Some select queries can be converted to single FETCH task minimizing latency.
Currently the query should be single sourced not having any subquery and should not have
any aggregations or distincts (which incurs RS), lateral views and joins.
0. none : disable hive.version
1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only
2. more  : SELECT, FILTER, LIMIT only (support TABLESAMPLE and virtual columns)
</description>
</property
3.本地模式
有时Hive的输⼊数据量是⾮常⼩的。在这种情况下,为查询触发执⾏任务消耗的时间可能会⽐实际job的执⾏时间要多的多。对于⼤多数这种情况,Hive可以通过本地模式在单台机器上处理所有的任务。对于⼩数据集,执⾏时间可以明显被缩短。如何判断数据量的多少则根据输⼊⽂件的数量、⽂件的个数来判断(不建议全局开启,根据实际任务开始临时配置)。
#开启本地mr
ode.local.auto=true;
#设置local mr的最⼤输⼊数据量,当输⼊数据量⼩于这个值时采⽤local  mr的⽅式,默认为134217728,即128M
ode.local.auto.inputbytes.max=50000000;
#设置local mr的最⼤输⼊⽂件个数,当输⼊⽂件个数⼩于这个值时采⽤local mr的⽅式,默认为4
ode.local.auto.input.files.max=10;
4.MapJoin
如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发⽣数据倾斜。可以⽤MapJoin把⼩表全部加载到内存在map端进⾏join,避免reducer处理。
#默认为true
set vert.join =true;
#⼤表⼩表的阈值设置(默认25M⼀下认为是⼩表)
set hive.mapjoin.smalltable.filesize=25000000;
早期的版本中需要我们⼿动开启,对于⼤表join⼩表必须将⼩表放在⼤表前⾯才能起到效果;新版本中
前后都已经得到了优化。但是具体控制⼤⼩表的阈值我们则可以根据实际⾃⾏控制。
5.Group By
默认情况下,Map阶段同⼀Key数据分发给⼀个reduce,当⼀个key数据过⼤时就倾斜了。并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端进⾏部分聚合,最后在Reduce端得出最终结果。
#开启Map端聚合参数设置是否在Map端进⾏聚合,默认为True
set hive.map.aggr =true
#在Map端进⾏聚合操作的条⽬数⽬
upby.mapaggr.checkinterval = 100000
#有数据倾斜的时候进⾏负载均衡(默认是false)
upby.skewindata =true
当选项设定为 true,⽣成的查询计划会有两个MR Job。第⼀个MR Job中,Map的输出结果会随机分
布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从⽽达到负载均衡的⽬的;第⼆个MR Job再根据预处理的数据结果按照Group By Key分布到Reduce中(这个过程可以保证相同的Group By Key被分布到同⼀个Reduce 中),最后完成最终的聚合操作。
6.笛卡尔积
尽量避免笛卡尔积,join的时候不加on条件,或者⽆效的on条件,Hive只能使⽤1个reducer来完成笛卡尔积。
7.动态分区调整
关系型数据库中,对分区表Insert数据时候,数据库⾃动会根据分区字段的值,将数据插⼊到相应的分区中,Hive中也提供了类似的机制,即动态分区(Dynamic Partition),只不过,使⽤Hive的动态分区,需要进⾏相应的配置。
#开启动态分区功能(默认true,开启)
dynamic.partition=true
#设置为⾮严格模式(动态分区的模式,默认strict,表⽰必须指定⾄少⼀个分区为静态分区,nonstrict模式表⽰允许所有的分区字段都可以使⽤动态分区。)de=nonstrict
#在所有执⾏MR的节点上,最⼤⼀共可以创建多少个动态分区。
ax.dynamic.partitions=1000
#)在每个执⾏MR的节点上,最⼤可以创建多少个动态分区。该参数需要根据实际的数据来设定。⽐如:源数据中包含了⼀年的数据,即day字段有365个值,那么该参数就需要设置成⼤于365,如果使⽤默认值100,则会报错。
ax.dynamic.partitions.pernode=100
#整个MR Job中,最⼤可以创建多少个HDFS⽂件。与上⼀个值可以保持⼀致,⼀个符合实际的较⼤数值
ax.created.files=100000
#当有空分区⽣成时,是否抛出异常。⼀般不需要设置。
on.empty.partition=false
8.执⾏推测
在实际中可能因为种种原因,会造成同⼀个作业的多个任务之间运⾏速度不⼀致,有些任务的运⾏速度可能明显慢于其他任务(⽐如⼀个作业的某个任务进度只有⼀半,⽽其他所有任务已经运⾏完毕),则这些任务会拖慢作业的整体执⾏进度。为了避免这种情况发⽣,Hadoop 采⽤了推测执⾏(Speculative Execution)机制,它根据⼀定的法则推测出“拖后腿”的任务,并为这样的任务启动⼀个备份任务,让该任务与原始任务同时处理同⼀份数据,并最终选⽤最先成功运⾏完成任务的计算结果作为最终结果。
设置开启推测执⾏参数:Hadoop的l⽂件中进⾏配置
<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&duce.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的推测执⾏:
<property>
<name>duce.ution</name>
<value>true</value>
<description>Whether speculative execution for reducers should be turned on. </description>
</property>
不过hive本⾝也提供了配置项来控制reduce-side的推测执⾏:
<property>
<name>duce.ution</name>
<value>true</value>
<description>Whether speculative execution for reducers should be turned on. </description>
</property>
9.JVM重⽤
JVM重⽤对Hive的性能具有⾮常⼤的影响,特别是对于很难避免⼩⽂件的场景或task特别多的场景,这类场景⼤多数执⾏时间都很短。Hadoop的默认配置通常是使⽤派⽣JVM来执⾏map和Reduce任务的。这时JVM的启动过程可能会造成相当⼤的开销,尤其是执⾏的job 包含有成百上千task任务的情况。
JVM重⽤可以使得JVM实例在同⼀个job中重新使⽤N次。N的值可以在Hadoop的l⽂件中进⾏配置。通常在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>
这个功能的缺点是,开启JVM重⽤将⼀直占⽤使⽤到的task插槽(任务队列),以便进⾏重⽤,直到任务完成后才能释放。如果某个“不平衡的”job中有某⼏个reduce task执⾏的时间要⽐其他Reduce task消耗的时间多的多的话,那么保留的插槽就会⼀直空闲着却⽆法被其他的job使⽤,直到所有的task都结束了才会释放。
10.严格模式
Hive提供了⼀个严格模式,可以防⽌⽤户执⾏那些可能意想不到的不好的影响的查询。通过设置属性de值为默认是⾮严格模式nonstrict (建义⽣产环境开启)。
<name>de</name>
<value>strict</value>
<description>
The mode in which the Hive operations are being performed.
In strict mode, some risky queries are not allowed to run. They include:
Cartesian Product. --限制笛卡尔积的查询
No partition being picked up for a query. --对于分区表,除⾮where语句中含有分区字段过滤条件来限制范围,否则不允许执⾏
Comparing bigints and strings -- ⽐较bigints、strings
Comparing bigints and 、doubles. -- ⽐较bigints、doubles
Orderby without limit.  -- 对于使⽤了order by语句的查询,要求必须使⽤limit语句
</description>
</property>
sql优化的几种方式
11.并⾏执⾏
Hive会将⼀个查询转化成⼀个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段。或者Hive执⾏过程中可能需要的其他阶段。默认情况下,Hive⼀次只会执⾏⼀个阶段。不过,某个特定的job可能包含众多的阶段,⽽这些阶段可能并⾮完全互相依赖的,也就是说有些阶段是可以并⾏执⾏的,这样可能使得整个job的执⾏时间缩短。不过,如果有更多的阶段可以并⾏执⾏,那么job 可能就越快完成。通过设置参数parallel值为true,就可以开启并发执⾏。不过,在共享集中,需要注意下,如果job中并⾏阶段增多,那么集利⽤率就会增加。
#打开任务并⾏执⾏(默认false)
parallel=true;
#同⼀个sql允许最⼤并⾏度,默认为8。
parallel.thread.number=16;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。