hadoop&hive优化

说明:本文主要涉及hadoop、hive查询统计基础知识及一些进阶方法 

MR基础知识

重用Text等Writable类型

不要用context.write(new Text(...),new Text(...))
而是用
key.set(...);
value.set(...);

使用StringBuilder

不要使用Formatter,不要使用StringBuffer,不要介意使用+

//StringBuilder sb = new StringBuilder(); //警告全局变量勿用

map(....) {
   StringBuilder sb = new StringBuilder()
}

通过DistributeCache加载文件(配置文件,字典等)

熟悉掌握并使用Combiner、Partitioner、Comparator三大神器

MR注意事项

解析字符串优化

很多人喜欢使用string split方法,简单快捷,但是split底层每次使用的时候要重新new Pattern(),new几千万次效率何其较低下,

推荐使用StringUtils或者正则表达式预先声明

谨慎使用全局变量

StringBuilder、集合类,有些时候一个劲儿装载数据,却不清空,导致full gc,甚至集群一下子增加十几个T的空间,把集群搞死。

创建过多自定义的Counter

可以用,但是不要超过50个。

hive常见优化手段

分区裁剪(Partition Pruning)

where分区中的条件,会提前生效,不必特意做子查询。可参考hive执行计划树解析hive.optimize.pruner=true,hive默认为true

列裁剪(Column Pruning)

在读取数据的时候,只读取查询需要用到的列。
hive.optimize.cp=true,hive默认为true

笛卡尔积

尽量避免笛卡尔积,join的时候不加on条件,hive只能使用1个reduce来完成笛卡尔积。(on条件只支持等值操作)

 Union ALL

先做union all再做join或group by等操作可以有效减少MR过程,尽管又多个select但是只有一个MR过程。

Mulite-Insert & Multi-Group by

读取一次,多个查询统计

FROM(
 $DEVICE_TEMP_TABLE_SQL
 ) temp_device_table

 insert overwrite local directory '$DEVICE_T_MOBILE_RESULT' 
 $DEVICE_T_MOBILE_SQL

 insert overwrite local directory '$DEVICE_WIFI_RESULT'  
 $DEVICE_WIFI_SQL

MAP端部分聚合

set hive.map.aggr =true,进行聚合函数操作sum、count等操作时,会在map端先进行一次聚合操作。

可以通过设置hive.groupby.mapaggr.checkinterval来控制map端聚合的数目,默认是100000

合并小文件

hive.merge.mapfiles = TRUE 是否合并map-only job的输出文件,默认为true

hive.merge.mapredfiles = FALSE 是否合并map-reduce的输出文件,默认为false,建议开启,

降低文件数据过多对hdfs带来的压力

hive.merge.size.per.task=256000000 合并文件的大小,默认为256M

本地作业

hive.exec.mode.local.auto=false,默认为false,建议开启。

处理小数据量作业时,使用本地模式可以使hive执行的更快些。满足如下job的条件才会触发本地作业

  1. job的数据大小必须小于参数hive.exec.mode.local.auto.inputbytes.max(默认128M)
  2. job的map数必须小于参数hive.exec.mode.local.auto.input.files.max(默认4)
  3. reduce的必须是0或者1

可用参数hive.mapred.local.mem,来设置local model下mapper和reduce task jvm heap size(在本地模式的最大内存量,以字节为单位,默认为0,不加限制,有hadoop自己控制)

善用order by、sort by、distribute by、cluster by

order by 全局排序

sort by 不是全局排序,只能保证在同一reduce输出有序

distribute by 根据distribute by指定的内容将数据分到同一reduce

cluster by 除了具有distiribute by的功能外,还会对字段进行排序,可以看做sort by + distribute by

hive join优化

说明一点:on值后面添加条件操作,和放在where后面条件判断,查询效率是一致的。但是对于外连接就不要这样子,会影响查询结果。

Map join

select关键字后面添加/+ MAPJOIN(tablelist) +/,tablelist中的表将会读入内存,必须是小表,最好不要超过10万以上。

亦庄集群开启了set hive.auto.convert.join = true参数,会自动判断走common join还是map join,
默认的文件大小是hive.mapjoin.smalltable.filesize 25M

大表作为驱动表 

hive总是按照从左到右的先后顺序执行,

例a表:大表,b表:小表,数据分布均与。

 a表   b表
key     key
10     10
10     20
10     20
20
20
20

a jon b on a.key = b.key,需要计算a.10 = b.10 4+3=7, a.20 = b.20 4+6=10,合计比较17次

b join a on b.key = a.key,代价 b.10=a.10 2+3=5,b.20 = a.20 3+6=9,合计比较14次

如果是千万级的大表,显然b表 join a表查询效率要高很多。

数据倾斜

参数调节

hive.groupby.skewindata=true,万能解决方法。有数据倾斜的时候尽心负载均衡,当选项设定为true,生成的查询计划会有两个MR JOB。第一个MR job中,Map的输出结果集合会随即分不到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By key有可能分发到不同的Reduce中,从而达到负载均衡的目的;第二个MR job再根据预处理的数据结果按照Group By Key分不到Reduce中(这个过程可以保证相同的Group By Key被分不到同一个Reduce中),最后完成最终的聚合操作。

NULL值处理

不合法的值直接过滤掉,或者把null的值加上一个随机数,把倾斜的数据分发到不同的reduce上。

count distinct大量相同值

可以先做一次distinct操作,在做count操作,值为null的值也可以直接过滤掉

例计算全站mau

 select cast(count(1) as int)+1 from (select distinct id  from iplog where log_date>='2013-11-09' and log_date<='2013-12-09' and id>0) t;

Group by维度过多

采用sum() group by 方式来替代count(distinct)完成计算

参考资料

数据倾斜总结:http://www.alidata.org/archives/2109

hive优化:http://www.alidata.org/archives/595

hive参数优化:http://www.cnblogs.com/yshb/p/3147710.html

你可能感兴趣的:(hadoop&hive)