Hive优化核心思想是把Hive Sql当做MapReduce去优化。
1、select查询本表、where进队本表字段做过滤时不会转为MapReduce执行。
原因:Hive抓取策略配置。Set hive.fetch.task.conversion=none/more;
默认配置为more.所以对部分查询不会转为MapReduce执行。
2、Hive sql转为MapReduce的过程:1)抽象语法树。2)查询块。3)逻辑查询计划。4)物理查询计划。5)优化执行
可以使用explain (在加extends 会更详细的展示) select count(*) from psn;查看sql的执行计划。分析计划效率。
3、Hive sql之前介绍的都是运行在集群上。在本机测试时可以设置在本地。
设置:set hive.exec.mode.local.auto=true;设置完成hive sql就会运行在本地上。而不通过yarn集群。所以效率比较高。
注意:hive.exec.mode.local.auto.inputbytes.max默认值为128M。它表示文件加载的最大值。若大于该配置依然会在集群运行。
4、开启并行计算。
设置下面参数,开启并行计算:
set hive.exec.parallel=true
比如 select t1.ct,t2.ct1 from (select count(name) ct from psn) t1,(select count(id) ct1 from psn)t2;
正常情况下会分成多个job依次执行。但是如果第一个select count 和第二个同时执行,就会提高了效率。
注意这个参数:hive.exec.parallel.thread.number;
意思为一个sql中允许并行执行的job个数的最大值。默认为8.
5、严格模式。
开启严格模式:set hive.mapred.mode=strict; 默认为nonstrict
此模式对于查询的限制:1.对于分区表,必须where对于分区字段的过滤。2、order by 必须包含limit做输出限制。3、限制执行笛卡尔积查询。
通过限制提升查询效率。
6、Hive 排序。
Order by 是对全部查询结果的全排序。只允许有一个reduce处理,所以效率非常低(尤其是数据量大时慎用)。
Sort by :是对于单个reduce内的数据排序。
Distribut by :reduce间的排序(分区排序)。常和Sort by一起使用达到分区有序和区间内有序。
distribute by column sort by column asc|desc
cluster by 相当于Distribut by +Sort by 但是cluster by 不能配合desc asc指定排序规则。
7、Hive jion
思想: jion计算时将小表放在左边。希望将小表加载到内存,大表逐行取出与其对比。这样的方式会比较节约内存。
Map Join:在Map端完成Jion.
两种实现方式:
【1】、手动添加MapJoin标记。/*+ */ 里定义的表识别为小表
select /*+ mapjoin(p)*/ p.id,p1.id from psn p join psn24 p1 on p.id=p1.id;
【2】、开启自动的MapJoin,程序根据表的大小自动识别为哪个是小表.设置以下配置启动:set hive.auto.convert.join = true;
注意:第二个参数的意思为,当既写了/*+ */标记又开启的自动识别时。标记无效。不配置这个的话,如果标记与自动识别都配置了,那么标记生效。
8、Hive Jion 尽可能使用相同的连接建(会转化为一个MapReduce作业)。
9、大表Jion大表:
【1】空key过滤。有时Join超时是因为某些key对应的数据太多。相同key对应的数据都是在相同的reducer中运算的。从而内存不够。此时,分析这些key,很多情况key对应的是异常数据,我们可以再sql语句中进行过滤。
【2】空key转换。当key为空时,有时会对应很多数据。这些数据也要join到结果中。这时可以使表中的空key赋予随机数,使数据均匀分布在reducer中。
10、map-side聚合。
通过设置开启map-site聚合:set hive.map.aggr=true;
原理:就是map之后shuffle之前的combiner阶段。先对数据做一部分聚合。减少文件,减少shuffle阶段的IO,进而提高性能。
11、合并小文件。(注意:这里合并小文件原理没理解清楚。)
12、控制map及reduce数量:
13、Hive JVM重用。
场景:小文件过多,task很多
原理:提前按配置申请一定资源(槽),是多个task同时进行。
配置:set mapred.job.reuse.jvm.num.tasks=n; n为插槽个数
缺点:设置开启后task会一直占用资源,不论task是否运行。直到整个job(全部task)全部完成,才会释放所有的插槽资源。