hive容易产生数据倾斜的场景:
1)group by 不和聚合函数一起使用
2)reduce join
3) count(distinct )
1 好的模型设计
2 解决数据倾斜
在map端进行join,减少reducetask数据量
聚合函数和group by结合使用
null值不参与连接
3 减少job数
4 设置合理的map reduce的task数,手动指定一般不超过datanode的95%
5 对小文件进行合并,减少maptask
6 单个作业最优不如整体最优
order by 性能比较低的
sort by 局部排序
distribute by 分桶|分区
cluster by 分+排序
hive 笛卡尔积是没有关联建的关联 转换为MR的时候 mapkey
select * from a,b; select * from a join b;
若需求中必须做笛卡尔积,最好自己设定一个关联建
表1:1000万 条数据
表2:20万 条数据 1-1000
1)对小表额外添加一个建 作为关联使用的建 随机产生
大表进行复制操作 小表有多少个不同的关联建 大表就复制多少份 大表的每一个复本的关联建就是小表中其中一个数据的关联建
2)大表随机生成一个关联建
小表进行复制 大表的不同的关联建的份数
第二种方式更加合理
1)reducetask的并行度高 分区数量更多
2)每一个reducetask中数据量不是太大
select cast(rabd()*1000 as int),* from stu;
hive 1.2.1 1.2.2 不支持
hive 2.3.2 支持 但是性能低 mapkey
select * from stu where age in(18,20,30,34);
mapkey null value:表的所有数据
高效替代方案:
left semi join
inner join
能使用多重查询 不使用单重查询
数据插入:能使用多重插入 不使用单重插入
减少对表的扫描次数 提升性能的
from 表
insert into table ... where
insert into ......
使用multi group by:
from area
insert overwrite table temp1
select Provice,city,county,count(rainfall) from area where data="2018-09-02" group by provice,city,count
insert overwrite table temp2
select Provice,count(rainfall) from area where data="2018-09-02" group by provice
使用multi group by 之前必须配置参数:
hive.multigroupby.singlemr
true
maptask|reducetask--->yearnchild----》container----->jvm虚拟机
一个container中 只会执行一个maptask|reducetask 这个container就会销毁
4节点 1300M 10maptask
一个节点上 会启动多个maptask任务 资源不够
我们如果可以container重用 性能提升
mapred.job.reuse.jvm.num.tasks=1
这个参数决定的是一个container中可以重复运行的task的数量 默认值1 代表一个container只能运行一个task
mapred.job.reuse.jvm.num.tasks=3;
一个container中可以运行3个maptask|reducetask任务的 节省了启动和销毁的时间 提升了性能
CombineTextInputFormat 文件合并的输入类 不会将文件进行物理合并的 将文件输入maptask的时候将多个小文件作为一个切片输入的
hive 2 默认开启小文件合并了
set hive.merge.mapfiles = true ##在 map的任务结束时合并小文件,默认合并
set hive.merge.mapredfiles = false ## true 时在 MapReduce 的任务结束时合并小文件 默认不合并的
set hive.merge.size.per.task = 25610001000 ##合并文件的大小 最大不超过256M
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
##执行 Map 前进行小文件合并 hive文件输入的默认类 mapreduce的map端的文件输入类 默认会进行小文件合并
经验:不超过 datanode*0.95
1)提升抽样性能 散列 一个桶中的数据就可以直接作为抽样数据的
2)获得更高的查询处理效率。
连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
如何获取每一个桶中的数据
tablesample(BUCKET x OUT OF y);
x:抽取的是第几个桶簇的数据
y:桶簇的个数
桶簇:半个/一个或多个桶组成的一个集合
y=1 代表的是有1个桶簇 3个桶的数据全部在一个桶簇中
y=2 2个桶簇 一个桶簇中1.5个桶
y=3 3个桶簇 一个桶簇---1个桶的数据
x=2 代表抽取的是第2个桶簇
select * from stu_buk tablesample(bucket 1 out of 3);
y=6 6个桶簇 一个桶簇---0.5个桶
x=2 获取的是第二个桶簇
第一个桶的后半部分? age%3=0
select * from stu_buk tablesample(bucket 2 out of 6);
轮询式划分桶簇的 每个桶先按照顺序划分 轮询
select * from stu_buk tablesample(bucket 4 out of 6);
若表中的数据量很大,而查询的时候通常按照某一个字段进行过滤查询,这时表需要创建为分区表的 提升查询性能 减少扫描范围
select * from test where date=""; 全表扫描的
建分区表
分区字段 date 按照分区字段进行分开存储的 每一个分区对应一个目录
表—》hdfs对应的是目录 表相当于目录的管理者
在进行按照分区字段查询的时候相当于查询的一个分区的小表 提升查询性能
常用的分区字段:时间|地域
时间:多级分区 /year/month/day/hour
日志数据的原始表一般建分区表 按时间分区
表关联:
1)大小 (小小) 小表不能超过23.8M,在hive中默认的是map端的join
参数:
hive.auto.convert.join
true
Whether Hive enables the optimization about converting common join into mapjoin based on the input file size
指定是否启动mapjoin
hive.mapjoin.smalltable.filesize
25000000
The threshold for the input file size of the small tables; if the file size is smaller
than this threshold, it will try to convert the common join into map join
mapjoin对于小表的大小的限定 默认大小不得超过25M左右
较小表大小不超过23.8M 执行的都是mapjoin
2)大* 中
中表超过23.8M 放在缓存中足够的,但默认执行的是reducejoin(容易产生数据倾斜的)
强制执行mapjoin /+mapjoin(需要放在缓存中的中表)/
user 1T log 300M
select /*+mapjoin(a)*/ * from log a join user b on a.userid=b.userid;
执行的仍然是mapjoin
3)大* 大
user 1T 所有用户 10 有效匹配的数据2G 200M
log 存储一天的数据 10G
1)其中的一个表进行瘦身
user 1T 所有用户 userid
log 存储一天的数据 10G userid(大量的重复数据) 一个用户10条日志信息
log表 50
瘦身的表 user表 根据log中的有效的userid表瘦身user表
瘦身user表:
1)获取log的去重之后的userid
select distinct userid from log where userid is not null;
2)使用user表关联上面的数据 user表的瘦身
select
/*+mapjoin(a)*/b.*
from (select distinct userid from log where userid is not null) a join user b on a.userid=b.userid;
3)开始进行真正的关联
select
/*+mapjoin(c)*/*
from (
select
/*+mapjoin(a)*/b.*
from (select distinct userid from log where userid is not null) a join user b on a.userid=b.userid
) c join log d on c.userid=d.userid;
注意:
1)hive中支持多条件的关联 and,不支持or连接
select * from a join b on a.id=b.id or a.name=b.name;
2)hive中尽量使用等值连接
不支持非等值连接 非等值连接 数值
3)hive关联的时候 经验:将小表放在左侧 大表放右侧
a join b on … join c on …
a:1000
b:10000
c:100000
默认在map端执行聚合
建表 stored as textfile|sequencefile|rcfile