【大数据】HIVE常用优化

一 hive性能优化

优化并非完全针对时间,也可以针对内存:

  • 防止倾斜问题
  • 使用Map join
  • 设置合理的map reduce的task数
  • 裁剪过滤
  • 小文件进行合并
  • 降低内存占用

二 HIVE数据倾斜问题

1. 参数调优
set hive.groupby.skewindata=true

数据倾斜时负载均衡,查询时变成了两个MR,第一个map随机分配reduce,然后再做第二个MR。

2.SQL解决数据倾斜
⑴ 慎用count(distinct)

我们来看下面的sql:

SELECT COUNT( DISTINCT id ) FROM TABLE_NAME WHERE ...;

【大数据】HIVE常用优化_第1张图片
由于使用了distinct,导致在map端的combine无法合并重复数据,Hive在处理COUNT这种“全聚合(full aggregates)”计算时,它会忽略用户指定的Reduce Task数,而强制使用1。
我们可以采用下面的方式优化:

SELECT COUNT(*) FROM (SELECT DISTINCT id FROM TABLE_NAME WHERE) t;

【大数据】HIVE常用优化_第2张图片

⑵ 空key转换

主键为 null 的情况,就可能会出现数据倾斜的问题。原因是 Hive 中,主键为 null 值的项会被当做相同的 Key 而分配进同一个计算 Map。我们可以把null的过滤出来。

三 使用Map join

利用hive进行join连接操作,相较于MR有两种执行方案,一种为common join(默认),另一种为map join ,map join是相对于common join的一种优化,省去shullfe和reduce的过程,大大的降低的作业运行的时间。
开启map join:

set hive.auto.convert.join = true;              //默认为false,是true开启map join
set hive.mapjoin.smalltable.filesize=200000000; //设置mapjoin小表的文件大小为20M,小表阈值

场景(满足一个即可):

  • 关联操作中有一张表非常小,map join在map阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在map是进行了join操作,省去了reduce运行的效率也会高很多
  • 不等值的链接操作,如果将不等条件写在where中,那么在common join的mapreduce过程中会进行笛卡尔积,运行效率特别低,如果使用mapjoin操作,在map的过程中就完成了不等值的join操作,效率会高很多

四 设置合理的map reduce的task数

set hive.exec.reducers.bytes.per.reducer=<number>   //  ①优先级最高
set hive.exec.reducers.max=<number>                 //  ②优先级中
set mapreduce.job.reduces=<number>                  //  ③优先级最低
  • ①设置在执行SQL的过程中每个reducer处理的最大字节数量
  • ②用于设置最大reducer数量
  • ③执行sql会生成多少个reducer处理数据
  • reducer的数量并不是越多越好,我们知道有多少个reducer就会生成多少个文件,小文件过多在hdfs中就会占用大量的空间,造成资源的浪费。如果reducer数量过小,导致某个reducer处理大量的数据(数据倾斜就会出现这样的现象),没有利用hadoop的分而治之功能,甚至会产生OOM内存溢出的错误。使用多少个reducer处理数据和业务场景相关,不同的业务场景处理的办法不同。

五 裁剪过滤

  • 列裁剪 读取查询中所需要用到的列,这样做节省了读取开销,中间表存储开销和数据整合开销。
hive.optimize.cp=true(默认值为真)
  • 分区裁剪 可以在查询的过程中减少不必要的分区
hive.optimize.pruner=true(默认值为真)

六 小文件进行合并

我们知道文件数目小,容易在文件存储端造成瓶颈,给 HDFS 带来压力,影响处理效率。对此,可以通过合并Map和Reduce的结果文件来消除这样的影响。

是否合并Map输出文件:hive.merge.mapfiles=true(默认值为真)
是否合并Reduce 端输出文件:hive.merge.mapredfiles=false(默认值为假)
合并文件的大小:hive.merge.size.per.task=256*1000*1000(默认值为 256000000)

七 降低内存占用的方式

1.GROUP BY替代COUNT(DISTINCT)
select count(distinct col) from A;   // ①
select count(1) from (select 1 from A group by col) alias;   // ②
  • distinct需要将col列中的全部内容都存储在一个内存中,可以理解为一个hash结构,key为col的值,最后计算hash结构中有多少个key即可得到结果。很明显,需要将所有不同的值都存起来。内存消耗可能较大。
  • group by的方式是先将col排序。而数据库中的group一般使用sort的方法,即数据库会先对col进行排序。而排序的基本理论是,时间复杂为nlogn,空间为1.,然后只要单纯的计数就可以了。优点是空间复杂度小,缺点是要进行一次排序,执行时间会较长。
  • 两中方法各有优劣,在使用的时候,我们需要根据实际情况进行取舍。
2.写sql的时候要注意把小表放在join的左边

原因是在 Join 操作的 Reduce 阶段,位于 Join 操作符左边的表的内容会被加载进内存,将条目少的表放在左边,可以有效减少发生 OOM 错误的几率。

你可能感兴趣的:(hadoop)