Hive调优策略——并行执行、严格模式、JVM重用、压缩、设置mapper和reducer个数 & 小文件合并

目录

1. 并行执行

2. 严格模式

3. JVM重用

4. 压缩

(1)开启Map输出阶段压缩(snappy压缩)

(2)开启Reduce输出阶段压缩(snappy压缩)

5. 合理设置Map和Reduce个数

(1)小文件过多,减少map数

(2)小文件进行合并

(3)文件比较大、文件处理逻辑复杂,增大map数

(4)合理设置Reduce个数


1. 并行执行

当系统资源比较空闲时,将hive执行中多个job阶段并行执行,这样使得整个job的执行时间缩短。

set hive.exec.parallel=true;              //打开任务并行执行
set hive.exec.parallel.thread.number=16;  //同一个sql允许最大并行度,默认为8。

2. 严格模式

hive的严格模式可以防止用户执行哪些可能产生不好影响的查询。

开启严格模式需要将hive.mapred.mode的值从默认的nonstrict,修改为strict;开启严格模式可以禁止以下5种类型的查询


    hive.mapred.mode
    strict
    
      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.(查询时没有分区)
        Comparing bigints and strings.(比较bigint和string)
        Comparing bigints and doubles.(比较bigint和double)
        Orderby without limit.(orderby的时候没有limit不会执行)


(1)限制笛卡尔积的查询

(2)对于使用了order by语句的查询,后面必须接limit语句,防止处理排序的那个reducer执行时间过长

(3)对于分区表,需要加上where 分区字段='~',不允许用户扫描全表,不允许扫描所有分区

3. JVM重用

当小文件过多或者task特别多的时候,Hadoop默认配置通常是派生JVM来执行map和Reduce任务,一个task伴随一次JVM的启动和销毁,当一个job中包含成百上千个task任务时,JVM重用可以使得JVM实例在同一个job中重复使用n次,n的值在mapred-site.xml文件中配置。

通常在10-20之间,设定为-1表示无论task有多少个都重用一个JVM实例。


  mapreduce.job.jvm.numtasks
  10
  How many tasks to run per jvm. If set to -1, there is
  no limit. 
  

JVM重用的缺陷是:遇到数据倾斜可能会出问题

开启JVM重用将一直占用正在使用的task插槽,直到job完成后才会释放。例如有3个节点都开启JVM重用,一个job有10个task,任务运行到第9个task时卡住了,卡在节点1上;节点2和节点3空闲,如果此时又进来一个job,那么这3个节点的集群JVM会卡在第一个job上,第二个job不会运行。

在实际生产环境一般都会开启JVM重用。

4. 压缩

对于hive中数据采取合适的存储格式和压缩格式,会提高数据的存储和查询效率。

综合考虑压缩比和sql查询效率,一般hive常用存储格式是orc和parquet,都是列式存储;

hive中常用压缩格式是snappy和lzo。

Hive的几种常见压缩格式(ORC,Parquet,Sequencefile,RCfile,Avro)的读写查询性能测试

(1)开启Map输出阶段压缩(snappy压缩)

开启map输出阶段压缩可以减少job中map和Reduce task间数据传输量。具体配置如下:

1. 开启hive中间传输数据压缩功能
hive (default)>set hive.exec.compress.intermediate=true;

2. 开启mapreduce中map输出压缩功能
hive (default)>set mapreduce.map.output.compress=true;

3. 设置mapreduce中map输出数据的压缩方式
hive (default)>set mapreduce.map.output.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;

(2)开启Reduce输出阶段压缩(snappy压缩)

当Hive将输出写入到表中时,输出内容同样可以进行压缩。配置如下:

1. 开启hive最终输出数据压缩功能
hive (default)>set hive.exec.compress.output=true;

2. 开启mapreduce最终输出数据压缩
hive (default)>set mapreduce.output.fileoutputformat.compress=true;

3. 设置mapreduce最终数据输出压缩方式
hive (default)> set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;

4. 设置mapreduce最终数据输出压缩为块压缩
hive (default)> set mapreduce.output.fileoutputformat.compress.type=BLOCK;

 

5. 合理设置Map和Reduce个数

(1)小文件过多,减少map数

开启的map数越多,启动和关闭JVM花费的时间也就越多;

如果一个任务有很多小文件(远小于块大小128M),每个小文件会被当做一个块,每个块用一个map任务来完成,这样小文件的逻辑处理时间远小于每一个map任务启动和初始化的时间,就会造成很大的资源浪费;并且同时可执行的map数是受限的。

这种情况就需要减少map数。

(2)小文件进行合并

第一种情况,在map执行前合并小文件,减少map数

set hive.input.format= org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

第二种情况,在map-reduce任务结束后,对生成的小文件进行合并

1. 在map-only任务结束时合并小文件,默认true
set hive.merge.mapfiles = true;

2. 在map-reduce任务结束时合并小文件,默认false
set hive.merge.mapredfiles = true;

3. 当输出文件平均大小小于该值时,启动一个独立的MR进行文件合并
set hive.merge.smallfiles.avgsize = 16777216;

4. 合并后文件大小,默认256M
set hive.merge.size.per.task = 268435456;

(3)文件比较大、文件处理逻辑复杂,增大map数

例如有一个127M的文件,正常会用一个map来处理,但这个文件只有一个或两个小字段,却有几千万行记录,也就是说map的处理逻辑比较复杂,这种情况如果还用一个map去处理,肯定会比较耗时,这种就需要增加map数,使得每个map处理的数据量减少,提高执行效率。

依据Hadoop中map源码公式:

computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
(默认切片大小blockSize是128M,minSize大小默认是1M,maxSize默认>128M)

增加mapper个数,减小切片大小:减小maxSize的值<128M,那么切片大小为maxSize

减少mapper个数,增大切片大小:增大minSize的值>128M,那么切片大小为minSize

eg:减小切片大小,增加切片个数,增加mapper数
set mapreduce.input.fileinputformat.split.maxsize=100;

(4)合理设置Reduce个数

在Hadoop的mapred-default.xml文件中修改,设置每个job的Reduce个数:-1代表使用默认值。

set mapreduce.job.reduces = -1

ps:reduce个数并非越多越好,过多启动和初始化reduce会消耗时间和资源,

另外一个reduce产生一个输出文件,如果reduce过多,会产生很多小文件;如果这些小文件作为下一个job的输入,也会出现小文件过多的问题。

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Hive)