Hive性能优化大全

核心思想:是将hive程序当做mapreduce程序进行优化;

hive中sql语句转化为MapReduce的过程,整个编译过程分为6个阶段:

1).Antlr定义Sql的语法规则,完成SQL词法,语法解析,将SQL转化为 抽象语法树AST Tree。

2).遍历抽象语法树AST Tree,抽象出查询的基本组成单元 QueryBlock查询块。

3).遍历QueryBlock,翻译为执行操作树OperatorTree。

4).逻辑层优化器进行OperatorTree变换,合并不必要的ReduceSinkOperator,减少shuffle数据量。

5).遍历OperatorTree,翻译为MapReduce任务。

6).物理层优化器进行MapReduce任务的变换,生成最终的执行计划。

1、 显示查询计划:

在hive命令行输入:explain extended select count(*) from bigdata_user;

可以查看该sql执行的整个过程。

2、hive的运行方式:

1).集群模式:需要先将本地程序打成Jar包,上传集群,如果执行出错,需要继续修改上传,在执行jar包,循环往复,影响开发效率。

2).本地模式:在hive中执行 set hive.exec.mode.local.auto=true;

只能在测试和开发环境进行,并且限制输入文件的大小不能超过128M,如果大于该配置,仍会以集群方式运行。对于小数据执行时间可以明显被缩短。

3、并行执行:

一次SQL计算中允许并行执行的job个数的最大值,Hive会将一个查询转化成一个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段。由于job包含多个阶段,而这些阶段并非完全互相依赖,所以可以启用并行执行,缩短整个job的执行时间(硬件资源充足,默认并行度是8)

设置参数:hive.exec.parallel.number

4、 严格模式:

设置参数为:

set hive.mapred.mode = strict;

1)、笛卡尔积查询:join查询不使用on语句而是使用where语句

关系型数据库的执行优化器可以高效地将where语句转化成on语句,hive并不会执行这种优化。

2)、查询没有选择分区:对于分区表,where语句中无分区字段过滤条件

不允许用户扫描所有分区,因为分区表通常数据量巨大,没有限制分区的查询可能会消耗巨大资源。

3)、order by没有limit语句:

order by 为了执行排序过程,会将所有的结果数据分发到同一个reducer中进行处理,增加limit语句可以防止reducer额外执行很长一段时间。

4)、int类型数据与string和double类型比较

5、排序方式:

order by :对于查询结果做全排序,只允许有一个reduce处理 ,会造成数据倾斜, 一般不建议使用。严格模式下,必须结合limit来使用。

sort by :对于单个reduce的数据进行排序,分区内数据有序。

distribute by: 分区排序,分区间有序。经常和sort by结合使用

(distribute by column sort by column asc|desc的方式)

cluster by: sort by+distribute by,无法指定升序和降序规则。

6、Hive Join

如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会默认把执行Common Join,即在Reduce阶段完成join。整个过程包含Map、Shuffle、Reduce阶段。Map Join:在map端完成join,没有了Shuffle,就没有Reduce。节省查询时间。

1)、SQL方式,在SQL语句中添加MapJoin标记(mapjoin hint)

语法:

SELECT  /*+ MAPJOIN(smallTable) */  smallTable.key,  bigTable.value

FROM  smallTable  JOIN  bigTable  ON  smallTable.key  =  bigTable.key;

2)、开启自动的MapJoin

通过修改以下配置启用自动的mapjoin:

set hive.auto.convert.join = true;

(该参数为true时,Hive自动对左边的表统计量,如果是小表就加入内存,即对小表使用Map join)

相关配置参数:

hive.mapjoin.smalltable.filesize; 

(大表小表判断的阈值,如果表的大小小于该值则会被加载到内存中运行)

hive.ignore.mapjoin.hint;

(默认值:true;是否忽略mapjoin hint 即mapjoin标记)

hive.auto.convert.join.noconditionaltask;

(默认值:true;将普通的join转化为普通的mapjoin时,是否将多个mapjoin转化为一个mapjoin)

hive.auto.convert.join.noconditionaltask.size;

(将多个mapjoin转化为一个mapjoin时,其表的最大值)

7.map_side聚合

是否在map端执行combine

通过设置以下参数开启在Map端的聚合:

set hive.map.aggr=true;

相关配置参数:

hive.groupby.mapaggr.checkinterval:

map端group by执行聚合时处理的多少行数据(默认:100000)

hive.map.aggr.hash.min.reduction:

进行聚合的最小比例(预先对100000条数据做聚合,若聚合之后的数据量/100000的值大于该配置0.5,则不会聚合)

8、合并小文件

每个小文件会启动一个map任务,浪费资源;

文件数目小,容易在文件存储端造成压力,给hdfs造成压力,影响效率.;

将map和reduce的小文件进行合并,大于256M后不再参与合并;

设置合并属性

是否合并map输出文件:hive.merge.mapfiles=true

是否合并reduce输出文件:hive.merge.mapredfiles=true;

合并文件的大小:hive.merge.size.per.task=256*1000*1000

9、去重统计

数据量小的时候无所谓,数据量大的情况下,由于COUNT DISTINCT操作需要用一个Reduce Task来完成,这一个Reduce需要处理的数据量太大,就会导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换。

10、控制Hive中Map及Reduce的数量

1)、Map数量相关的参数

mapred.max.split.size

一个split的最大值,即每个map处理文件的最大值

一个机架上split的最小值

mapred.min.split.size.per.rack

一个节点上split的最小值

mapred.min.split.size.per.node

一个split的最大值,即每个map处理文件的最大值

2)、Reduce数量相关的参数

mapred.reduce.tasks

强制指定reduce任务的数量

hive.exec.reducers.bytes.per.reducer

每个reduce任务处理的数据量

hive.exec.reducers.max

每个任务最大的reduce数

11、JVM重用

预先申请了一些资源,避免了重复对资源的重复申请和销毁工作(类似于线程池)

适用场景:

1)、小文件数过多

2)、task个数过多

通过 set mapred.job.reuse.jvm.num.tasks=n; 来设置(n为task插槽个数)

缺点:设置开启之后,task插槽会一直占用资源,不论是否有task运行,直到所有的task即整个job全部执行完成时,才会释放所有的task插槽资源!

猜你喜欢

转载自blog.csdn.net/weixin_42312342/article/details/89601026