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;
来源:CSDN
作者:yx06140830
链接:https://blog.csdn.net/yx06140830/article/details/104059411