Hive优化

一、hive的随机抓取策略

理论上来说,Hive中的所有sql都需要进行mapreduce,但是hive的抓取策略帮我们 省略掉了这个过程,把切片split的过程提前帮我们做了。

Fetch抓取的模式
可以通过 set hive.fetch.task.conversion查看,有以下3种模式(默认是more ):

none:所有涉及hdfs的读取查询都走mapreduce任务;
mininal:在进行简单的select *,简单的过滤或涉及分区字段的过滤时走mr;
more:在mininal模式的基础上,增加了针对查询语句字段进行一些别名的计算操作。

二、本地运行模式

(处理小数据集的优化)

大多数的 Hadoop Job 是需要 Hadoop 提供的完整的可扩展性来处理大数据集的。不过,
有时 Hive 的输入数据量是非常小的。在这种情况下,为查询触发执行任务消耗的时间可能
会比实际 job 的执行时间要多的多。对于大多数这种情况, Hive 可以通过本地模式在单台机
器上处理所有的任务。对于小数据集,执行时间可以明显被缩短。
用户可以通过设置 hive.exec.mode.local.auto 的值为 true ,来让 Hive 在适当的时候自动
启动这个优化。


更改为本地模式:
hive> set hive.exec.mode.local.auto=true
注意:
hive> set hive.exec.mode.local.auto.inputbytes.max=134217728     ---> 128M
(默认值就是128)
表示加载文件的最大值,若大于该配置仍然会以集群的方式去运行。

当我们开发或者测试阶段,可以去使用本地模式进行运行,默认是集群模式
但是,这里有个问题,当我们去更改为本地模式的时候,在year的页面上就看不到
任务的执行情况了。

 

 三、并行计算

通过设置以下参数开启并行模式(默认是false)
set hive.exec.parallel=true;

注意1:hive.exec.parallel.thread.number
(一次SQl计算中允许并行执行的job个数最大值,默认是8个)

举例:
select t1.n1,t2.n2 from (select count(ename) as n1 from emp) t1,(select count(dname) as n2 from dept) t2;


注意2:有时候开启并行计算运行时间并没有不开启的快,那是因为,资源的问题。
需要两套资源,资源申请会浪费点时间,最多可以并行8个,默认是8个。
所以,并行的越多,不一定是越快,因为它涉及到一个资源申请的策略。

四、严格模式

1.严格模式 :

    hive中的一种模式,在该模式下禁止一些不好SQL的执行

2.Hive的严格模式不允许哪些SQL执行

2.1 禁止分区表全表扫描

分区表往往数据量大,如果不加分区查询会带来巨大的资源消耗 。

例如以下分区表 SELECT DISTINCT(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

正确写法: ​ SELECT DISTINCT(planner_id) FROM fracture_ins WHERE planner_id=5 AND hit_date=20120101;

 

2.2 禁止排序不加limit

​ 排序最终是要都进到一个Reduce中操作,防止reducer额外执行很长一段时间

举例:

​ SELECT * FROM fracture_ins WHERE hit_date>2012 ORDER BY planner_id; ​

报错: ​ FAILED: Error in semantic analysis: line 1:56 In strict mode,limit must be specified if ORDER BY is present planner_id ​

正确写法就是增加一个limit关键字:

 SELECT * FROM fracture_ins WHERE hit_date>2012 ORDER BY planner_id LIMIT 100000;

 

2.3 禁止笛卡尔积(表之间join不加条件)

​ 笛卡尔积可以简单理解为这样的一种形式: A={a,b}, B={0,1,2},则 A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}

举例:

SELECT * FROM fracture_act JOIN fracture_ads; ​

解决方法(加where或on条件):

 ​ SELECT * FROM fracture_act JOIN fracture_ads WHERE fracture_act.planner_id = fracture_ads.planner_id;

 

2.4总结: 

查询限制:
1、对于分区表,必须添加where对于分区字段的条件过滤
2、order by 语句必须包含limit输出限制
3、表之间的join必须加where或者on条件限制
这些限制是帮助我们提高查询效率的。

3.严格模式怎样开启

// 查看当前严格模式的状态
set hive.mapred.mode;
// 设置为严格模式
set hive.mapred.mode=strict;
// 设置为非严格模式
set hive.mapred.mode=nonstrict;

五、Hive排序

在以下博客有详细的描述:

http://t.csdnimg.cn/Qo95b

(1)order by 对于查询结果做全排序,只允许有一个reduce处理
注意:它会把我们所有的字段或者查询结果全部放在一个reduce里进行处理,当数据量较大时候,有可能reduce执行不完,所以并不是好的方式。

(2)sort by 对于单个reduce进行排序 但是我们将每个reduce里面进行排序,没有考虑到
每个reduce之间的排序,所以也并不是最优解。


最优解:distribute by 分区排序(指定分区方式局部排序),通常结合sort by一起使用
           (distribute by column sort by column asc|desc)

(4)cluster by 相当于distribute by + sort by

 注意,虽然是两个结合,但是我们也不去用它,原因是cluster by只能升序排序。

 

六、合并小文件

1、hadoop不适合存储小文件

原因:一个小文件对应一个block块,增加资源消耗,其次一个block对于一条元数据,增加主节点压力,如果这样的小文件越多,元数据增多,可能会导致主节点空间不足。
2、MR不适合处理小文件

原因:一个block块默认会产生一个切片,一个切片产生一个map任务,小文件一多则map任务的数量增多,那么map任务申请资源的时间会变长。


3、Hive不适合处理小文件

底层会转化为mapreduce任务执行,原因同上。

优化方案:合并小文件
文件数目小,容易在文件存储端造成压力,给hdfs造成压力,影响效率
设置合并属性
  是否合并map输出文件: hive.merge.mapfiles=true
  是否合并reduce输出文件: hive.merge.mapredfiles=true
  合并文件的大小: hive.merge.size.per.task=256*1000*1000

七、控制map和reduce的数量(一般情况下我们不去动它)

控制Hive中Map以及 Reduce的数量
Map数量相关的参数:
mapred.max.split.size;一个split的最大值,即每个map处理文件的最大值
mapred.min.split.size.per.node个节点上split的最小值
mapred.min.split.size.per.rack一个机架上spit的最小值


Reduce数量相关的参数:
mapred.reduce.tasks;强制指定reduce任务的数量
hive.exec.reducers.bytes.per.reducer每个reduce任务处理的数据量
hive.exec.reducers.max每个任务最大的reduce数

 

八、JVM重用(一次性申请一部分资源)

mapreduce加载的方式是懒加载,当执行任务需要资源的时候再去申请资源

当需要申请的资源过多的时候,我们可以申请一部分资源,全部执行完毕后再释放,
比我们申请一个释放一个要快。

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


缺点:
设置开启后,task插槽会一直占用资源,无论是否有task进行,直到所有的task,
即整个job全部执行完毕后,才会释放所有的task插槽,所以我们要合理地设置这个n
(比如,我们设置申请了10个,但是现在来了6个,剩下4个插槽会在job全部执行完毕之前一直占用资源)

九、数据倾斜(重点)

1.发生数据倾斜的原因与解决思路

Hive中数据倾斜一般发生在表关联(join)的情况下,发生数据倾斜的原因可能是由于键分布不均匀到reduce中,导致reduce中数据量过大,使得reduce任务会一直卡在某个进度上,进而导致整个mapreduce任务失败。

解决思路:让这些大量相同的键分散到不同的reduce中去处理,让reduce之间负载均衡,将来可以在执行一个reduce整合每个reduce中的数据,虽然两个reduce使得作业量变多了,但是总比一个reduce出不来结果要好。

 

2、表之间的关联:

1、小表join小表,数据量少,就算发生发生数据倾斜,也能执行出结果,那么就不用考虑这种情况。

2、小表join大表(小表小到可以放到内存的程度)

优化方案:map-join,将小表放入到内存中去,在map端进行关联表的操作,不在reduce拉取的时候关联

3、大表join大表

优化方案: map-side

2.1 小表join大表优化方案具体实现过程:

join计算的时候,将小表(驱动表)放在join的左边
Map join:在Map端完成join


两种实现方式:
1、sql方式,在sql语句中添加Mapjoin标记(mapjoin hint)
加入语法糖
select /*+MAPJOIN(A)*/ * from A join B on (A.key=B.key);
举例:
select /*+MAPJOIN(smallTable)*/ smallTable.key bigTable.value from smallTable join bigTable on smallTable.key=bigTable.key;


2、设置参数
通过修改以下配置启用自动的mapjoin:
set hive.auto.convert.join=true;              (在hive3.X版本,默认是开启的)
(注意:该参数为true的时候,Hive自动对左边的表统计量,如果是小表,就加入到内存,即对小表使用Mapjoin)

其他相关配置参数
hive.mapjoin.smalltable.filesize;(默认25M,大表小表判断的阈值,如果表的大小小于该值则会被加载到内存中运行。)
hive.ignore,mapjoin.hint;(默认值:true;是否忽略mapjoin hint的标记)
hive.auto.convert.join.noconditionaltask;(默认值:true;将普通的join转换为mapjoin时,是否将多个mapjoin转化为一个mapjoin)
hive.auto.convert.join.noconditionaltask.size;(将多个mapjoin转化为一个mapjoin时,这个表的最大值)


注意:尽可能使用相同的连接键,如果不同,多一个join就会多开启一个mapreduce,执行速度变得慢。

2.2 大表join大表解决方案具体实现过程:

以下是两种优化方案:
(1)key过滤:
有时join超时是因为某些key对应的数据太多,而相同key对应的数据都会发送到相同的 reducer上,从而导致内存不够。
此时我们应该仔细分析这些异常的key,如果这些key对应的数据是异常数据,我们可以使用SQL语句进行过滤。
但是我们一般拿到的数据都是经过ETL数据清洗过后的,一般影响不大。
(2)key转换:
如果数据不是异常数据,我们可以使key字段打上前缀,经过hash算法使得数据随机均匀地分不到不同的reducer上,之后在执行一个reduce整合每个reduce中的数据。(加盐处理)

Map-Side聚合
通过设置以下参数开启在Map端的聚合
set hive.map.aggr=true;

(一定要进行开启,虽然进行了两个mapreduce,但是当数据倾斜发生的时候,很多时候会根本跑不出结果,卡死在99%或者100%,慢总比出不来结果要好)
相关配置参数
  hive. groupby mapaggr. checkinterval;
  map端 igroup by执行聚合时处理的多少行数据(默认:10000
  hive.map.aggr.hash.min.reduction;比例(若聚合之后的数据100大该0.5,map端聚合使用的内存的最大值
  hive.mapaggr.hashforce.flush.memory.threshold;map端做聚合操作是has表的最大可用内容,大于该值则会触发fush
  hive.groupby.skewindata-是否对 GroupBy产生的数据倾斜做优化,默认为false(重要)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值