hive的四大by
order by (全局排序)
例子:
select * from emp order by sal;
只有一个reduce,无论设置多少个reduce,都是一个
优点:全局排序
缺点:当数据量大的时候,耗时长,效率低适用较小数据量的场景
sort by (分区内排序)
对每一个reduce内部的数据进行排序,全局结果来说不是排序的,也就是说只能保证每一个reduce输出的文件中的数据是按照规定字段排序的,适用于数据量大,但是对排序要求不严格的场景,可以大幅提高执行效率;
set mapreduce.job.reducers=10;
例子:
select * from emp sort by sal desc;
需要预先设置reduce个数,reduce结果文件内部有序,全局不是,可能是无序的;
distribute by (分区排序)
控制特定的key到指定的reducer,方便后续的聚合操作,类似于MR中自定义分区,一般结合sort by 使用,需要预先设置reduce个数,否则不会启动相应的reducer进行任务的执行,导致最后不能完全分区。
set mapreduce.job.reducers=10;
例子:
select * from emp distribute by deptno sort by sal desc;
注意:
1.distribute by要在sort by 之前
2.distribute by的分区规则是根据分区字段的hash码与reduce的个数去模后,余数相同的分到一个分区;
cluster by
当distribute by 和sort by 字段相同的时候,可以写成cluster by
但是这个排序只能升序;
select * from emp cluster by deptno;
select * from emp distribute by deptno sort by deptno;
题目
有一张订单表,然后取gmv为top 100 的用户,假设这张订单表有1亿的用户有gmv,求如何去取;
第一种:
select * from dwd_order_df order by gmv desc limit 100;
弊端:全局排序显然不行,耗时长,效率低;
所以可不可以多个reduce,分区内排序,最后再全局排序呢;
select * from (
select * from dwd_order_df distribute by city sort by gmv desc limit 100) x
order by gmv desc limit 100;
hive 的三大join
common/shuffle/reduce join
最普通的join,产生shuffle,且这个会在reduce端做join
mapjoin
通常用在大小表关联
小表的阈值
set hive.mapjoin.smalltable.filesize=25123456;--25M
select /*+MAPJOIN(b)*/ count(1)
from a --大表
join b --小表
on a.id=b.id
可以将b表放在内存,在map端做join,join就发生在map操作的时候,每当扫描一个大表的数据,就要去内存看小表,有没有与之相等的,继而进行关联。
优点:map端的join优势,没有shuffle;
还一种写法,自动将小表扔到内存中;
set hive.auto.convert.join=true;
select count(1)
from a
join b
on a.id=b.id;
SMB join
sort merge bucket
大表和大表关联呢?
a 5亿
b 10亿
1.a b 都是分桶的
2.a b 分桶的key必须是join key
3.设置一些参数
set hive.auto.convert.sortmerge.join=true;
set hive.optimize.bucketmapjoin=true;
set hive.optimize.bucketmapjoin.sortedmerge=true;
hive的参数优化
mapjoin
set hive.mapjoin.smalltable.filesize=25123456;
set hive.auto.convert.join=true;
combiner 在map端聚合
set hive.map.aggr=true;
在map端进行聚合的条数
set hive.groupby.mapaggr.checkinterval=100000;
负载均衡
数据倾斜的时候
set hive.groupby.skewindata =true;
当选定为true,生成的查询计划会产生两个MR 的job
1.先加随机前缀,聚合一次;
2.再去掉随机前缀,在聚合一次;
UDF
实现一个简单的UDF
select say_hello('word');
hello:world
java实现:
第一步在pom.xml文件里面,导入hive包依赖
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>3.1.2</version>
</dependency>
第二步,建class,实现方法
package hiveUDF;
import org.apache.hadoop.hive.ql.exec.UDF;
public class UDFHello extends UDF {
public String evaluate(String name){
return "Hello : " + name;
}
}
然后进行打包,上传服务器hive/lib,赋权
[root@vagary lib]# rz
[root@vagary lib]# chmod 777 mapreduce-1.0.jar
进入hive,添加jar包
hive (default)> add jar /home/vagary/app/hive/lib/mapreduce-1.0.jar ;
Added [/home/vagary/app/hive/lib/mapreduce-1.0.jar] to class path
Added resources: [/home/vagary/app/hive/lib/mapreduce-1.0.jar]
然后看一下jar包
hive (default)> list jars;
/home/vagary/app/hive/lib/mapreduce-1.0.jar
接下来创建函数
hive (default)> CREATE TEMPORARY FUNCTION say_hello as "hiveUDF.UDFHello";
OK
Time taken: 0.578 seconds
然后测试一下
hive (default)> select say_hello('world');
OK
_c0
Hello : world
Time taken: 2.556 seconds, Fetched: 1 row(s)