HIVE优化

佐手、 提交于 2020-01-21 19:53:28

Fetch抓取

	Hive中某些情况查询可以不必使用MapReduce计算。
	例子:select * from tmp;
	hive.fetch.task.conversion=more;
	默认开启

本地模式

	set hive.exec.mode.local.auto=true;
	开启本地模式

小表、大表JOIN

	新版本hive已经对小表join大表和大表join小表进行了优化。小表放在左边和右边影没有明显区别。

大表JOIN大表

	1、空key过滤
	有时候join超时是因为某些key对应的数据太多,而相同key对应的数据都会发送到相同的reducer上,从而导致内存不够。
	正常情况下这些空key都是脏数据,肯定需要被过滤掉的。
	2、空key转换
	但是有时候出现很多空key的情况,但是相应的数据不是脏数据,所以我们要对key为空的字段赋一个随机值,使得数据可以随机均匀分不到不同的reducer上。

例:

select IF(key IS NULL, concat('random', rand()), key) AS key from tmp;

如果相应的key为空的话,对key做一下随机数处理。

MapJoin(小表join大表)

	如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将join操作转化为Common Join,即在reducer阶段完成join,这行很容易发生数据倾斜。可以用MapJoin把小表全部加载到内存中在map端进行jion,避免reducer处理。
	1、开启MapJoin参数
	set hive.auto.convert.join=true;//这个参数默认为true
	2、大表小表阈值设置(默认25M一下为小表)
	set hive.mapjoin.smalltable.filesize=25000000;
	3、工作机制

在这里插入图片描述
执行流程如下:

  • 首先是Task A,它是一个Local Task(在客户端本地执行的Task),负责扫描小表b的数据,将其转换成一个HashTable的数据结构,并写入本地的文件中,之后将该文件加载到DistributeCache中,该HashTable的数据结构可以抽象为:
    |key| value|
    | 1 | 26 |
    | 2 | 34 |
  • 接下来是Task B,该任务是一个没有Reduce的MR,启动MapTasks扫描大表a,在Map阶段,根据a的每一条记录去和DistributeCache中b表对应的HashTable关联,并直接输出结果。
  • 由于MapJoin没有Reduce,所以由Map直接输出结果文件,有多少个Map Task,就有多少个结果文件

Group By

	默认情况下,Map阶段下同一个key数据分发给一个reduce,当一个key数据过大时就倾斜了。
	并不是所有的局和操作都需要在Reduce端完成,很多聚合操作都可以现在Map端进行部分聚合,最后在reduce端得出结果
1、开启map端聚合参数设置
	1)是否在map端进行聚合,默认为true
		set hive.map.aggr=true;
	2)在map端进行聚合操作的条目数目
		set hive.groupby.mapaggr.checkpoint=10000
	3)有数据倾斜的时候进行负载均衡(默认为false)
		set hive.groupby.skewindata=true
当选项设定为true时,生成的查询计划会有两个MR。第一个mr中,map的输出结果会随机分不到reduce中,每个reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By key有可能被分不到不同的Reduce中,从而达到负载均衡的目的;第二个MR再根据预处理的数据结果按照Group By Key分布到Reduce中,最后完成聚合操作。

COUNT(distinct)去重统计

	数据量小的情况下无所谓,数据量大的情况下由于COUNT DISTINCT的全聚合操作,即使设定了reduce task个数,set mapred.reduce.tasks=100;hive也只会启动一个reducer,这就导致一个reducer处理的数据量太大。一般会用group by再count的方式替换

笛卡尔积

	严禁笛卡尔积,尽量避免笛卡尔积。join的时候不加on条件,或者无效的on条件,Hive只使用一个reducer来完成笛卡尔积

行列过滤

	列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用select *
	行处理:在分区剪裁中,当使用关联时,如果将副表的过滤条件写在where后面,那么就会先全表关联,之后再过滤。
select b.id from table1 a join table2 b ON a.id = b.id where b.id <=10; 

这种情况下,table2会先全表扫描。可以修改为:

select b.id from table1 a join (select id from table2 where id <=10) b ON a.id = b.id; 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!