1、hive组成
2、与mysql区别
hive mysql
数据量 大 小
速度 大 =》 快 小 =》 快
查询 增删改查
3、内部表和外部表区别
元数据、原始数据
删除数据时:
内部表:元数据、原始数据 全删除
外部表:元数据 只删除
在公司生产环境下,什么时候创建内部表,什么时候创建外部表?
在公司中绝大多数场景都是外部表。
自己使用的临时表,才会创建内部表;
4、4个by
order by 全局排序
sort by 排序
distribute By 分区 sort + d => 分区内排序
cluster By 排序和分区字段相同时使用
在生产环境order by用的多吗? 京东 oom 40-50t内存
s+d 在生产环境用的最多。分区内排序
c 比较少
5、系统函数
日 date_add date_sub
周 next_day
月 date_format last_day
解析json get_json_object
6、自定义函数
UDF/UDTF(hive)、UDAF(spark)
1)在项目中用UDF解析公共字段
2)在项目中使用UDTF解析的是事件字段
3)如果项目中不用自定义UDF、UDTF能解析吗?
可以用系统函数get_json_object
4)用系统函数能解决,为什么还要自定义?
自定义函数更灵活,方便调试bug
5)自定义UDF步骤?
定义类,继承UDF,重新里面evaluate方法
6)自定义UDTF步骤
定义类,继承G...UDTF ,重写3个方法 初始化、process、关闭
打包=》上传到集群=》在hive里面创建永久函数
7、窗口函数
rank over
手写topN
8、优化
1)mapjoin默认打开,不要关闭;
2)行列过滤 join where =>where join
1 亿 join 1 亿 条 where 1 条
3)创建分区表(天); 分桶(对数据不太清楚 ,采样)
4)小文件
(1)CombineHiveInputformart 减少切片,进而减少Maptask
(2)开启JVM重用
(3)merge maponly任务,默认功能打开
MapReduce任务,需要打开merge功能。
执行完任务之后,会将小于16m的文件,合并到256m(hive的块大小)
5)压缩 好处:减少磁盘空间,减少网络传输; 坏处:增加了解压缩计算
6)采用列式存储orc、parquet 提高查询效率;提高压缩的比例 100g=>10g 5-6g
id name age
1 zs 18
2 lisi 19
3 wangwu 20
行 1 zs 18 2 lisi 19 3 wangwu 20
select age from user 随机读写
列 1 2 3 zs lisi wangwu 18 19 20
select age from user 顺序读写:18 19 20
7)替换引擎:
mr 基于磁盘 可靠性高 效率低
数据量大,计算时间长 周、月、年
tez 基于内存 可靠性差 效率高
临时调试代码,即席查询
spark 基于内存+磁盘 可靠性居中 效率居中
每天定时任务
8)在map端开启combiner(不影响最终业务逻辑)
9)合理设置map个数和reduce个数;
map个数怎么设置? 切片 max(0,min(块大小,Long的最大值))
128m数据对应1g内存
9、数据倾斜
1)数据倾斜长啥样?
2)怎么产生的数据倾斜?
不同数据类型关联产生数据倾斜
情形:比如用户表中user_id字段为int,log表中user_id字段既有string类型也有int类型。当按照user_id进行两个表的Join操作时。
后果:处理此特殊值的reduce耗时;只有一个reduce任务
默认的Hash操作会按int型的id来进行分配,这样会导致所有string类型id的记录都分配到一个Reducer中。
解决方式:把数字类型转换成字符串类型
select * from users a
left outer join logs b
on a.usr_id = cast(b.user_id as string)
bug 记录: https://www.jianshu.com/p/2181e00d74dc
3)解决数据倾斜的方法?
(1)group by
注:group by 优于distinct group
解决方式:采用sum() group by的方式来替换count(distinct)完成计算。
(2)mapjoin
(3)开启数据倾斜时负载均衡
set hive.groupby.skewindata=true;
思想:就是先随机分发并处理,再按照key group by来分发处理。
操作:当选项设定为true,生成的查询计划会有两个MRJob。
第一个MRJob 中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的GroupBy Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;
第二个MRJob再根据预处理的数据结果按照GroupBy Key分布到Reduce中(这个过程可以保证相同的原始GroupBy Key被分布到同一个Reduce中),最后完成最终的聚合操作。
点评:它使计算变成了两个mapreduce,先在第一个中在 shuffle 过程 partition 时随机给 key 打标记,使每个key 随机均匀分布到各个 reduce 上计算,但是这样只能完成部分计算,因为相同key没有分配到相同reduce上。
所以需要第二次的mapreduce,这次就回归正常 shuffle,但是数据分布不均匀的问题在第一次mapreduce已经有了很大的改善,因此基本解决数据倾斜。因为大量计算已经在第一次mr中随机分布到各个节点完成。
(4)控制空值分布
将为空的key转变为字符串加随机数或纯随机数,将因空值而造成倾斜的数据分不到多个Reducer。
注:对于异常值如果不需要的话,最好是提前在where条件里过滤掉,这样可以使计算量大大减少
实践中,可以使用case when对空值赋上随机值。此方法比直接写is not null更好,因为前者job数为1,后者为2.
使用case when实例1:
select userid, name from user_info a
join (
select case when userid is null then cast (rand(47)* 100000 as int )
else userid end from user_read_log
) b on a.userid = b.userid
使用case when实例2:
select '${date}' as thedate,
a.search_type,
a.query,
a.category,
a.cat_name,
a.brand_id,
a.brand_name,
a.dir_type,
a.rewcatid,
a.new_cat_name,
a.new_brand_id,
f.brand_name as new_brand_name,
a.pv,
a.uv,
a.ipv,
a.ipvuv,
a.trans_amt,
a.trans_num,
a.alipay_uv
from fdi_search_query_cat_qp_temp a
left outer join brand f
on f.pt='${date}000000' and case when a.new_brand_id is null then concat('hive',rand() ) else a.new_brand_id end = f.brand_id;
如果上述的方法还不能解决,比如当有多个JOIN的时候,建议建立临时表,然后拆分HIVE SQL语句。
10、杂七杂八
1) Hive里边字段的分隔符用的什么?为什么用\t?有遇到过字段里边有\t的情况吗,怎么处理的?
hive 默认的字段分隔符为ascii码的控制符\001(^A),建表的时候用fields terminated by '\001'
遇到过字段里边有\t的情况,自定义InputFormat,替换为其他分隔符再做后续处理
2)MYSQL元数据备份
mysql 实现高可用
3) MySQL 超过字节数问题
将utf8修改为utf8mb4
4) union与union all
union 去重
union all 不去重