一、数据倾斜优化
1.合理设置Map数量
1.通常情况下,作业会通过input的目录产生一个或者多个map任务
主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小。
2.Map并非越多越好
如果一个任务有很多小文件,则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成最大的资源浪费。而且,同时可执行的map数是受限制的。
3.保证每个map处理接近128m的文件快,就没有问题吗?
有个一个127m的文件,默认情况下会用一个map去完成,但这个文件只有一个或者两个小字段,却有着几千万行记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。
2.小文件进行合并
在map执行前合并小文件,减少map数:CombineHiveInputFormat具有对小文件进行合并的功能(系统默认的格式)。HiveInputFormat没有对小文件合并功能。
set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
3.复杂文件增加Map数
当input的文件都很大,任务逻辑复杂,map执行非常慢的时候,可以考虑增加Map数,来使得每个map处理的数据量减少,从而提高任务的执行效率。
增加map的方法为:根据computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=128M公式,调整maxSize最大值。让maxSize最大值低于blocksize就可以增加map的个数。
set mapreduce.input.fileinputformat.split.maxsize = 100;
4.合理设置Reduce数
1.调整reduce个数方法(1)
(1)每个Reduce处理的数据量默认是256MB
set hive.exec.reducers.bytes.per.reducer = 256000000
(2)每个任务最大的reduce数,默认为1009
set hive.exec.reducers.max = 1009
(3)计算reducer数的公式
N=min(参数2,总输入数据量/参数1)
2.调整reduce个数方法(2)
在hadoop的mapred-default.xml文件中修改,设置每个job的Reduce个数
set mapreduce.job.reduces = 15;
3.reduce个数并不是越多越好
(1)过多的启动和初始化reduce也会消耗时间和资源;
(2)另外,有多少个reduce,就会有多少个输出文件,如果产生了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置reduce个数的时候也需要考虑这两个原则:处理大数据利用适合的reduce数;使单个reduce任务处理数据大小要合适;
二、并行执行
Hive会将一个查询转化成一个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段。或者Hive执行过程中可能需要的其他阶段。默认情况下,Hive一次只会执行一个阶段。不过某个特定的job可以包含众多的阶段,而这些阶段可能并非完全相互依赖的,也就是说有些阶段是可以并行执行的,这样可能使得整个job的执行时间缩短。不过,如果有更多的阶段可以并行执行,那么job可能就越快完成。
通过设置参数hive.exec.parallel值为true,就可以开启并发执行。不过,在共享集群中,需要注意下,如果job中并行阶段增多,那么集群利用率就会增加。
#打开任务并行执行
set hive.exec.parallel = true;
#同一个sql允许最大并行度,默认为8
set hive.exec.parallel.thread.number = 16;
三、严格模式
hive提供了一个严格模式,可以方式用户执行那些可能意识不到的不好的影响的查询。
通过设置属性hive.mapred.mode默认值是非严格模式(nonstrict)。开启严格模式需要修改hive.mapred.mode值为strict,开启严格模式可以禁止3种类型的查询。
<property><name>hive.mapred.mode</name><value>strict</value>
</property>
1.对于分区表,除非where语句中含有分区字段过滤条件来限制使用范围,否则不允许执行。就是用户不允许扫描所有的分区。进行这个限制的原因是,通常分区表都拥有非常庞大的数据集,而且数据迅速增加。没有进行分区限制的查询可能会消耗令人不可接受的巨大资源来处理这个表。
2.对于使用了order by语句的查询,要求必须使用limit语句。因为order by为了执行排序过程会将所有的结果数据分发到同一个Reduce中进行处理,强制要求用户增加这个limit语句可以防止Reduce额外执行很长一段时间。
3.限制笛卡尔积的查询。对关系数据库非常了解的时候可能在执行Join查询的时候不使用on语句而是用where语句,这样关系数据库的执行优化器就可以高效的将Where语句转换成on语句,但是Hive并不会执行这种优化,因此,如果该表很大,这个查询就会出现不可控的情况。
四、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</vaule>
</property>
这个功能的缺点是,开启jvm重启将会一直占用使用到的task插槽,以便使用重启,知道任务完成后才会释放。如果某个“不平衡的”job中有几个reduce task时间要比其他的reduce task消耗的时间多很多的话,那么保留的插槽将会一直空闲着缺无法被其他的job使用,直到所有的task都结束了才会释放。
五、查看语句执行计划
通过查看语句的执行计划单独对语句进行优化
基本语法:EXPLAIN [EXTENDED|DEPENDENCY|AUTHORIZATION] qurey