一、关于join中 出现数据倾斜的操作
这里我们需要设置两个参数:
1.1、hive.optimize.skewjoin = true;
如果join 中出现了数据倾斜, 应该设置成true。
1.2、set hive.skewjoin.key = 1000000;
这是join 的键对应的记录条数超过这个值则会进行优化。 而这个优化的措施是: 正常只有一个 job 来执行任务的, 优化后会出现两个 job 来执行任务。 当数据量达到1000000以上的时候, hive 会在启动一个job , 然后将原有的数据的key 加上一个随机数据打乱。 这样数据就会分到不同的节点上去计算。最后在原有打乱的基础上再做一次运算, 然后再启动一个job,恢复原来的 key ,再做一次运算。
二、关于maojoin的操作
2.1、其实maojoin的优化简单, 就是将我们的小表加载到缓存中, 这样所有的节点都可以访问到这个小表(有点像广播变量)。
怎么样开启这种方式?
set hive.auto.convert.join = true;
hive.mapjoin.smalltable.filesize 默认是25MB。 什么意思呢? 这个值是自己判断的, 就是当表格文件小于25MB的时候, 会自动启动mapjoin(这个最好手动开启)
手动开启方式: select /*+ maojoin(A)*/ f.a,f.b from A t join B f on (f.a=t.b and f.ftime=20110802)
其中A是小表,B是大表,这样我们是让join发生在map端。
注意:Mapjoin 使用的场景
1、关联操作中的一张小表
2、不等值的连接操作
3、mapjoin 最好是手动操作
三、对于bucket join 的操作
3.1 两个表以相同的方式划分分桶
3.2 两个表的桶的个数是倍数关系
例子:
creat table order (cid int , price float) clustered by (cid) into 30 buckets;
creat table customer(cid int, price string) clustered by (cid) into 60 buckets;
select price from order t join customer s on t.cid = s.id;
四、关于where和join的操作
4.1 优化前:select o*from order o join customer c on o.cid=d.id where o.time='2017-01-01';
优化后: select o.*from (select cid from order where time='2017-01-01') o join customer c on o.cid=c.id;
解释:优化前是先join后在where进行过滤的; 这样并没有减轻reduce的压力, 优化后是在mao端执行where,过滤器,然后再join的,这样大大降低了计算量
五、关于group by的操作
5.1、hive.groupby.skewindata=true;
如果group by 过程中出现数据倾斜, 应该设置成true。
5.2、set hive.groupby.maoagger.checkinterval=1000000;
group对应的键对应的记录数超过这个值则会进行优化,优化方案跟上面一样,也会运行来年各个job
六、对于Hive表的操作
6.1 分区: ‘表‘ 相当于一个大的目录,分区就是在这个大的目录下面创建一个个的小目录。而且分区字段不能是表中已经存在的字段, 分区的字段不是真实存在的, 这会显示给你看也可以查询, 但是不会存在于表中
分区分为静态分区和动态分区;
静态分区: 就是在 建表的时候指定分区
动态分区: set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
下面这个设置的默认值是strict。 strict是避免分区字段全部都是动态的, 也就是至少一个分区字段是由指定值的。我们一般用nonstrict,就是所有的分区字段都可以是动态的。
七、通过对hive job的优化来优化hive
7.1、并行化执行:JVE执行过程中的job是按照默认的顺序来执行的,如果没有太大的依赖关系,最好并行执行,减少执行的时间。每个查询被hive转化成多个阶段,有些阶段关联性不大,则可以并行执行,减少执行时间。
set hive.exec.parallel = true;
set hive.exec.parallel.thread.numbe = 16(默认8);
7.2、本地化执行:首先开启本地化执行: set hive.exec.model.local.auto = true;当一个job满足如下条件的时候才会真正使用本地模式来执行。
1、job的输入数据大小必须小于参数。
hive.exec.mode.local.auto.inputbytes.max (默认是128MB)
2、job的map数必须小于参数
hive.exec.node.local.auto.tasks.max (默认是4)
3、job的reduce必须是0或者是1
7.3、job合并输入的小文件
在集合中面临这样的问题,就是集群中有很多的小文件,这样会启动很多的(FileinputFormat会调用getsplit()方法对文件进行split,而split的个数决定了map的个数),而且这小文件执行的时间短,甚至还没有我们调用资源用的时间多,造成了集群资源的严重浪费。
解决: set hive.input.format = oar.apache.hadoop.hive.ql.io.CombineHiveInputForma 这样做以后,就会把多个split分片合并成一个。 而合并的文件数由 mapred.max.split.size 限制的大小来决定
7.4、job合并输出小文件
小文件的输出虽然不占用多大的磁盘空间 但是不要忘记无论多小的文件都会在HDFS的namenode上面存在一条元数据记录下来,很浪费资源。
解决: set hive.merge.smallfiles.avgsize = 2560000000;当输入文件平均大小小于该值。启动新job合并文件。
7.5、JVM的重利用:
JVM的重利用是可以使得JVM实例在同一个JOB中重新实用N次
方法: set mapred.reduse.jvm.num.tasks=10;
JVM的重用对hive的性能有很大的影响,特别是对小文件的场景或者是task特别多场景, 可以有效的减少执行时间。
7.6、关于数据的压缩:
两种压缩方式: 中间压缩和最终压缩
中间压缩: 减少网络传输的数据量, 中间压缩, 不需要压缩效果特别好,选择一个节省CPU耗时的压缩方式就行。
set hive.execc.compress.intermediate = true;
set hive.intermedia.compression.codec = org.apache.hadoop.io.compress.SnappyCode;
set hive.intermedia.compression.type = BLOCK; (按照块进行压缩)
hive查询的最总输出结果的压缩: 这个阶段可以选择一个压缩效果比价好的,这样可以境地集群存储的数据量,占用较小的空间。
set hive.exec.compress.out = true;
set mapred.output.compression.codec = org.apache.hadoop.io.compress.GzipCodec;
set hive.intermedia.compression.type = BLOCK;