Hive优化策略

语句级别优化

--列、分区裁剪

        查询过程中减少不必要的分区和列的查询。

--NULL处理

        -如无需对应字段可以在语句中直接过滤;

        -如需要可以提前筛选出来Union all关联输出,或者赋予新值(测试结果显示更优于前者)。

--不同类型字段关联

        会导致按照数据类型分配Reducer,导致数据倾斜,此处需要转化为同一类型。

--Join操作

        -大&小表:小表在左(会被先加载),大表在右。新版Hive已经处理了这个问题,会自动优化。

        -大&大表:减少查询量,如仅查询增量

        -map join:当一个表比较小时,可以开始此功能,将join从reducer提前到Map阶段。Join操作在Map阶段完成,不再需要Reduce,所以Map Task的个数就等于结果文件数。

//开启MapJoin功能
set hive.auto.convert.join = true;

--谓词下推

//默认开启
set hive.optimize.ppd = true; 

        -注意:如果使用外连接,则谓词下推会失效

--group by操作

        默认情况下,完成Map阶段后,同一key值会发送到同一reducer,此时一个key值过大的就会产生数据倾斜。针对这种情况有一下两种方式:

方法一:Map阶段部分聚合
    //开启Map聚合参数设置
    set hive.map.aggr=true
    //预先取N(此处设置为100000)条数据聚合
    set hive.grouby.mapaggr.checkinterval=100000
    //聚合后的条数/100000>0.5,则不再聚合
    set hive.map.aggr.hash.min.reduction=0.5
方法二:参数控制负载均衡(生成两个MR任务,第一阶段完成预处理,同key可能发送到不同的reducer中,完成负载均衡;第二阶段完成最终的聚合结果)
    //有数据倾斜的时候进行负载均衡
    set hive.groupby.skewindata = true

--count&distinct操作

       数据量大的情况下,count distinct需要一个reduce task完成,这一个reducer处理数据量太大。建议使用先group by再count的方式。

Map&Reduce级别优化

--减少Map数

        主要针对小文件(远小于文件块大小)较多的情况,如一个SQL查询对应共有10000个文件,但其中很多是远小于128MB的小文件,总大小只有1G,正常执行会用10000个map任务,将会耗费大量的Map计算资源。那么此时需要通过合并文件的方式来减少map数,如下:

//执行前进行小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

//mapred切分的大小,128MB
set mapred.max.split.size= 128000000;

//一个节点上split的至少的大小,数据在一个节点会合并,在多个不同的节点会把数据抓过来进行合并
set mapred.min.split.size.per.node= 100000000;

//一个交换机下split的至少的大小(这个值决定了多个交换机上的文件是否需要合并)
set mapred.min.split.size.per.rack= 128000000;

--增大Map数

        当input的文件比较大且任务逻辑复杂,从而导致map执行非常慢,此时可以考虑增加Map数,使得每个map处理的数据量减少,从而提高任务的执行效率。

//会将一个文件表,随机的分散到10个文件表中,再用这10个表代替上面sql中的表,会用10个map任务去完成
set mapred.reduce.tasks=10;

--Reduce数确定与调整

        在不指定reducer个书的情况下,hive会根据以下设定来确定个数

//每个reduce任务处理的数据量,默认为256M,在hive0.14.0之前默认是1G
hive.exec.reducers.bytes.per.reducer

//每个任务最大的reduce数,默认为1009,在hive0.14.0之前默认是999
hive.exec.reducers.max(每个任务最大的reduce数,默认为999)


以上,计算reducer数取其中最小值

--只有一个reducer的情况

        当操作都是全局的,如没有group by的汇总、使用order by、存着笛卡尔乘积

文件级别优化

--源头减少

        -使用distribute by分区,尽量少使用动态分区

        -减少reduce的数据

--文件合并

        -重建表,建表时减少reduce数量

        -hadoop archive文件归档

        -合并Map和Reduce的结果文件

//设置map端输出进行合并
set hive.merge.mapfiles = true

//设置reduce端输出进行合并
set hive.merge.mapredfiles = true

//设置合并文件的大小 
set hive.merge.size.per.task = 256000000

//当平均输出的文件大小小于该值时,启动一个独立的MapReduce任务进行文件merge  
set hive.merge.smallfiles.avgsize=16000000

系统级别优化

--计算引擎

        当前可以使用的计算引擎有MR、TEZ、SPARK,可以通过hive.execution.engine设置

--存储格式

        -TextFile:默认格式,行存储,数据不压缩;可以使用压缩算法,但是压缩后不切分。

        -SequenceFile:二进制文件,行存储,Hadoop API提供的一种二进制文件,以key-value的形式序列化到文件中。支持三种级别压缩,block级别最好。

        -RCFile:数据按行分块,每块按列存储,不支持任意方式的数据写操作,仅提供一种追加接口。

        -ORCFile:是RCFile的改良版本

        其中SequenceFile、RCFile、ORC格式的表不能直接从本地文件导入数据,数据要先导入到TextFile格式的表中,然后再从TextFile表中用insert导入到SequenceFile、RCFile表中。另外还有Parquet、AVRO等格式

--本地MR

        如果在hive中运行的sql本身数据量很小,那么使用本地MR的效率要比分布式的快很多。如下三个参数都满足时,才会使用本地MR:

//开启本地MR,默认关闭
set hive.exec.mode.local.auto=true;

//设置Local MR的最大输入数据量,当输入数据量小于时采用Local MR的方式
set hive.exec.mode.local.auto.inputbytes.max=134217728;

//设置Local MR的最大输入文件个数,当输入文件个数小于时采用Local MR的方式
set hive.exec.mode.local.auto.input.files.max=4;

--并行执行

        应用于可以并行运行的MR作业,例如在联接之前处理不同源表的作业。从Hive0.14开始,也适用于移动可以并行运行的任务,例如在多次插入期间移动文件以插入目标。通过set hive.exec.parallel=true设置。

上一篇:spring ioc 1


下一篇:GitHub 如何过滤某个作者的 MR 内容