hive优化
1、hive的随机抓取策略
hive中的sql都应该经过解析器,编译器,优化器和执行器产生mapreduce作业进行处理,但是在我们使用过程中,对于一些进行查询之类的任务的时候并没有产生mapreduce任务进行处理,这是因为hive的抓取策略帮我们省略了这个步骤,将split切片的过程体欠安帮我们做了,这个现象是hive中自己帮我们设置好了一个 set hive.fetch.task.conversion=more(默认情况下是这个参数值) 的参数,这个参数可以设置三种值(none mininal more)
Fetch抓取的模式:
查看抓取模式
set hive.fetch.task.conversion
设置:(注意!!这里设置的仅仅只是临时的,想要永久生效得前去更改配置文件中的)
set hive.fetch.task.conversion=none/miniinal/more
修改配置文件中的参数值:(在hive-site.xml中修改,在哪应该都知道吧)
将其中的value值改为三个值当中你想要的值
<property>
<name>hive.fetch.task.conversion</name>
<value>more</value>
<description>The level of query conversion to allow before it is sent to execution engine.</description>
</property>
none:设置成这个值的时候所有的涉及到hdfs的读取查询任务全部都要进行mapreduce任务
mininal:在进行简单的查询任务,简单的过滤任务以及分区字段的过滤的时候不会进行mapreduce任务
more:在mininal的基础上增加了针对查询语句字段进行一些别名的计算操作(就是在mininal基础上,如果增加了一些条件的字段,也不会走mapreduce任务)
2、本地运行模式
本地模式一般只在处理小数据集,开发测试阶段、资源限制的情况下开启
开启本地模式是将所有任务交给自己机器(运行hive的机器)来进行运行,是不会提交给yarn来进行执行
更改本地模式:
set hive.exec.mode.local.auto=true;
设置加载文件的最大值(默认128M )
set hive.exec.mode.local.auto.inputbytes.max=134217728
开启本地模式优缺点:
优点:执行速度变快,加快开发效率
缺点:不会提交到yarn上去,会产生一些隐患
1、故障恢复能力受限(yarn和其他一些系统能够提供强大的故障恢复机制,在本地模式下,这些机制无法生效,需要人为干预1,增加了运维的复杂度和风险)
2、可拓展性差(本地模式适合小数据集或进行简单的计算任务,但一旦过大,不提交给1yarn,hive的性能受限,无法充分1调用集群的计算能力)
3、调试和监控困难(在yarn等集群环境中,可以使用各种工具和日志对任务进行调试和监控,但是在本地模式下,该机器可能缺少对应的监控和调试方法)
4、资源隔离问题(在yarn的集群资源管理器中,每个任务都被分配了独立的资源,与其他任务隔离开了,但是在本地模式下,如果该机器同时运行了其他高负载的任务,那么会产生竞争资源现象,导致任务结束时间延长或者任务失败)
3、并行计算
开启并行计算(默认为false)
set hve.exec.parallel=true
hive中一次sql九三语序并行执行的最大job数量为8个
hive.exec.parallel.thread.number
注意!有时候开启了并行计算的运行时间比没有开启并行计算的运行时间还要长,这是因为并行计算需要申请资源,申请资源是需要时间的,所以并行的任务越多不是越多越好
4、严格模式(理解为增加一些限制)(工作中就是严格模式)
什么是hive的严格模式:
hive中的一种模式,在该模式下禁止一些不好的sql语句进行执行
严格模式下哪些sql不允许执行:
1、禁止分区表进行全表扫描
如果一个分区表你发现了可以全表进行扫描,那么严格模式就没有开启,分区表如果小,执行的还算快,但是一旦大了起来,那么会占用大量的资源去执行,所以查询的时候需要加分区查询
select distinict(planner_id) from fracture_ins where planner_id=5;
如果没有进行分区表分区查询会报如下错误:
FAILED: Error in semantic analysis: No Partition Predicate Found for Alias “fracture_ins” Table "fracture_ins
2、禁止排序不加 limit
如果查询一个数据量很大的表,不对该查询的行数进行限制,一个reducer需要执行很长一段时间,会占用大量资源
SELECT * FROM fracture_ins WHERE hit_date>2012 ORDER BY planner_id;
如果没加 limit 会出现如下报错:
FAILED: Error in semantic analysis: line 1:56 In strict mode,limit must be specified if ORDER BY is present planner_id
加个limit就行了
3、禁止笛卡尔乘积(笛卡尔乘积是什么不用再说了吧)
笛卡尔乘积:(算了,还是说一下吧,举个例子)
原始数据表A={a,b}, B={0,1,2}
笛卡尔乘积后
A×B=
SELECT * FROM fracture_act JOIN fracture_ads;
加上一个条件就可以了
SELECT * FROM fracture_act JOIN fracture_ads WHERE fracture_act.planner_id = fracture_ads.planner_id;
开启严格模式:
// 查看当前严格模式的状态
set hive.mapred.mode;
// 设置为严格模式
set hive.mapred.mode=strict;
// 设置为非严格模式
set hive.mapred.mode=nonstrict;
5、HIve排序(掌握 distribute by 和 sort by)
order by 对于查询结果做全排序,只允许有一个reduce进行处理,当数据量较大的时候,有可能reduce无法处理完成
sort by 和 distribute by 可以翻看之前的笔记(Hive分区和排序)
6、数据倾斜(非常重要!)
1、hive中出现数据倾斜都是出现在表进行关联的情况下
2、由于分布数据量的时候,某个reduce的数据量过大,导致reduce任务失败,然后整体的reduce会卡在某个进度,说明其中的某些 reduce 执行失败了
1)、小表 join 小表(数据量很小,不用管)
2)、小表 join 大表(map-join )
join在计算的时候,得将小表(驱动表)放在左边
这是在map阶段进行join(有两种方式开启)
1、sql方式:在sql语句中添加Mapjoin标记(mapjoin hint)
map的大小是根据切片大小来的,不用担心map的大小过大
加糖:
select /*+MAPJOIN(A) */* from A join B on (A.key=B.key);
--这里的A表是小表
2、自动开启mapjoin(默认时候开启的)
修改配置:
set hive.auto.convert.join=true;
(当参数为true的时候,hive会自动对左边的表进行大小计算,如果是小表的话,会进入到内存中去,就是对小表使用mapjoin)
相关配置参数:
1)、默认25M,大表和小表的1判断阈值,如果比它小就记载到内存中去
hive.mapjoin.smalltable.filesize;
2)、默认为true,这是个是是否忽略mapjoin hint 的标记
hive.ignore.mapjoin.hint;
3)、默认值为true,将普通的join转换成mapjoi时,是否将多个mapjoin转换成一个mapjoin
hive.auto.convert.join.noconditionaltask;
4)、将多个mapjoin转化成一个mapjoin时,这个表的最大值
hive.auto.convert.join.noconditionaltask.size;
3、尽量使用相同的连接键,如果不同,后面可能会有其他join,每个join都会产生一个mapreduce任务,执行速度会变慢
3)、大表 join 大表(map-side)
4、大表join大表的时候,因为数据量大是无法放入内存中的,只能发生在reduce过程中,这里有两个优化策略
a、空key过滤:
在关联之前将一些异常数据进行过滤,这样参与关联的数据量就会变少,将来进入reduce的时候就有可能会成功
b、空key转换:
将其中的key增加几个不同的前缀,这样他们的hash值就不同,并且设置多几个reduce,这样不同的key就会进入到不同的reduce中去进行处理,让reduce之间负载均衡,每个reduce都会有个结果,这时候可以再弄一个mapreduce进行合并,这种方式虽然慢,但是总比不用这种方法导致无法获取结果来的好,一般数据都是经过ELT数据清洗之后的,数据都比较规则,影响不大
ps:这时候还是解决不了就加机器吧,别折磨机器了,正常流程,提交工单申请,进行审核,根据需求提升配置
5、Map-side聚合
设置参数开启map端的聚合:(一定要进行开启)
set hive.map.aggr=true;
相关配置参数:
hive.groupby.mapagger.checkinterval;
map端 group by 执行聚合处理的时候默认处理10000行数据
hive.map.aggr.hash.min.reduction;
--这里的配置参数是用于控制map端hash聚合关闭条件,当hash表的容量与输入行的比例超过默认值0.5的时候,hive将不会再map端进行hash聚合,如果设置成1,就是hash聚合再map端永远不会被关闭
hive.mapaggr.hashforce.flush.memory.threshold;
--map端做聚合操作是has表的最大可用内容,大于该值则会触发
hive.groupby.skewindata
--是否对 GroupBy产生的数据倾斜做优化,默认为false(十分重要!!!)
6、数据倾斜,尽可能地让我们的数据散列到不同的reduce里面去,负载均衡(Hbase中热点数据)
7、合并小文件
1、hadoop不适合1存储小文件:
hadoop存储小文件会在元数据中添加该文件的路径信息,文件大小等信息,可能小文件的大小比存储该文件的一条元数据大小还要小,这样的小文件一多,元数据就会越大,而元数据是存储在主节点的NameNode上的,元数据越多,对主节点造成的压力越大,可能会导致主节点崩溃
2、mapreduce不适合处理小文件:
小文件越多,bolck块越多,切片越多,一个切片产生一个map任务,map任务数量越多,一个map任务是一个线程,产生线程是需要资源和时间的,申请资源也要时间,可能会导致申请资源时间过长或者资源不够
3、hive不适合处理小文件:
hive底层也是产生mapreduce任务,道理和mapreduce不适合处理小文件相同
设置合并属性:
1、是否合并map输出文件:
hive.merge.mapfiles=true;
2、是否合并reduce输出文件:
hive.merge.mapredfiles=true;
3、合并文件的大小:
hive.merge.size.per.task=256*1000*1000
这里的大小默认为256M(25610001000字节),在mapreduce任务结束的时候,hive会尝试将小文件合并为256M的文件
8、控制 map 和 reduce 的数量(一般情况不会去更改)
Map相关的参数设置:
1、设置每个map处理文件的最大值
mapred.max.split.size;
2、一个节点上split的最小值
mapred.min.split.size.per.node
3、一个机架上split的最小值
mapred.min.split.size.per.ramk
Reduce相关的参数化设置:
1、强制指定reduce任务的数量
mapred.reduce.tasks;
2、每个reduce任务处理的数据量
hive.exec.reducers.bytes.per.reducer
3、每个任务最大的reduce数量
hive.exec.reducers.max
9、JVM重用
当我们的小文件个数较多,task个数较多,申请的资源较多时,我们可以先申请一部分资源,在执行完毕之后再进行释放,这样比我们需要一个资源再去申请一个资源要快
如何设置:
set mapred.job.reuse.jvm.num.task=n;
缺点:
设置之后。task插槽会一直占用资源,无论是否有task进行,都会在所有task也就是整个 job全部执行完毕后进行释放,所以这里的n要合理的设置(比如设置的时候n是10个,但是我们只用到了6个,剩下的4个并没有用到,但是我们也无法使用,必须得等到整个 job执行完成之后才会释放掉)