hive笔记
1.大表join小表产生的问题,怎么解决?
mapjoin优化是在Map阶段进行join,而不是通常那样在Reduce阶段按照join列进行分发后在每个Reduce节点上进行join,不需要分发也就没有倾斜的问题,相反,Hive会将小表全量复制到每个Map任务节点(对于本例是dim_seller表,当然仅全量复制b表sql指定的列),然后每个Map任务节点执行lookup小表即可。
2.udf udaf udtf区别
UDF操作作用于单个数据行,并且产生一个数据行作为输出。大多数函数都属于这一类(比如数学函数和字符串函数)。
UDAF 接受多个输入数据行,并产生一个输出数据行。像COUNT和MAX这样的函数就是聚集函数。
UDTF 操作作用于单个数据行,并且产生多个数据行——-一个表作为输出。lateral view explore()
简单来说:
UDF: 返回对应值,一对一
UDAF:返回聚类值,多对一
UDTF:返回拆分值,一对多
3.hive有哪些保存元数据的方式,各有什么特点。
- 内存数据库derby,安装小,但是数据存在内存,不稳定
- mysql数据库,数据存储模式可以自己设置,持久化好,查看方便。
4.hive内部表和外部表的区别
内部表:加载数据到hive所在的hdfs目录,删除时,元数据和数据文件都删除
外部表:不加载数据到hive所在的hdfs目录,删除时,只删除表结构。
这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。
5.生产环境中为什么建议使用外部表?
- 因为外部表不会加载数据到hive,减少数据传输、数据还能共享。
- hive不会修改数据,所以无需担心数据的损坏
- 删除表时,只删除表结构、不删除数据。
6.insert into 和 override write区别?
insert into:将数据写到表中
override write:覆盖之前的内容。
7.hive的判断函数有哪些
hive 的条件判断(if、coalesce、case)
8.简单描述一下HIVE的功能?用hive创建表有几种方式?hive表有几种?
hive主要是做离线分析的
hive建表有三种方式
- 直接建表法
- 查询建表法(通过AS 查询语句完成建表:将子查询的结果存在新表里,有数据,一般用于中间表)
- like建表法(会创建结构完全相同的表,但是没有数据)
hive表有2种:内部表和外部表
9.线上业务每天产生的业务日志(压缩后>=3G),每天需要加载到hive的log表中,将每天产生的业务日志在压缩之后load到hive的log表时,最好使用的压缩算法是哪个,并说明其原因
- lzo压缩
优点:压缩/解压速度也比较快,合理的压缩率;支持split,是hadoop中最流行的压缩格式;支持hadoop native库;可以在linux系统下安装lzop命令,使用方便。
缺点:压缩率比gzip要低一些;hadoop本身不支持,需要安装;在应用中对lzo格式的文件需要做一些特殊处理(为了支持split需要建索引,还需要指定inputformat为lzo格式)。
应用场景:一个很大的文本文件,压缩之后还大于200M以上的可以考虑,而且单个文件越大,lzo优点越明显。
- snappy压缩
优点:高速压缩速度和合理的压缩率;支持hadoop native库。
缺点:不支持split;压缩率比gzip要低;hadoop本身不支持,需要安装;linux系统下没有对应的命令。
应用场景:当mapreduce作业的map输出的数据比较大的时候,作为map到reduce的中间数据的压缩格式;或者作为一个mapreduce作业的输出和另外一个mapreduce作业的输入。
10.若在hive中建立分区仍不能优化查询效率,建表时如何优化
hive分桶
对于每一个表(table)或者分区,Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。
Hive是针对某一列进行分桶。
Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。
11.union all和union的区别
union 去重
union all 不去重
12.如何解决hive数据倾斜的问题
1)group by
注:group by 优于 distinct group
情形:group by 维度过小,某值的数量过多
后果:处理某值的 reduce 非常耗时
解决方式:采用 sum() group by 的方式来替换 count(distinct)完成计算。
2)count(distinct)
count(distinct xx)
情形:某特殊值过多
后果:处理此特殊值的 reduce 耗时;只有一个 reduce 任务
解决方式:count distinct 时,将值为空的情况单独处理,比如可以直接过滤空值的行,
在最后结果中加 1。如果还有其他计算,需要进行 group by,可以先将值为空的记录单独处
理,再和其他计算结果进行 union。
3)mapjoin
小表不小不大,怎么用 map join 解决倾斜问题
使用 map join 解决小表(记录数少)关联大表的数据倾斜问题,这个方法使用的频率非常高,但如果小表很大,大到map join会出现bug或异常,这时就需要特别的处理。
4)不同数据类型关联产生数据倾斜
情形:比如用户表中 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)
5)开启数据倾斜时负载均衡
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 中随机分布到各个节点完成。
6)控制空值分布
将为空的 key 转变为字符串加随机数或纯随机数,将因空值而造成倾斜的数据分不到多个 Reducer。
注:对于异常值如果不需要的话,最好是提前在 where 条件里过滤掉,这样可以使计算量大大减少
13.hive性能优化常用的方法
1)MapJoin
如果不指定 MapJoin 或者不符合 MapJoin 的条件,那么 Hive 解析器会将 Join 操作转换成 Common Join,即:在 Reduce 阶段完成 join。容易发生数据倾斜。可以用 MapJoin 把小表全部加载到内存在 map 端进行 join,避免 reducer 处理。
2)行列过滤
列处理:在 SELECT 中,只拿需要的列,如果有,尽量使用分区过滤,少用 SELECT *。
行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在 Where 后面,那么就会先全表关联,之后再过滤。(先子查询,再关联)
3)列式存储
4)采用分区技术
5)合理设置 Map 数
(1)通常情况下,作业会通过 input 的目录产生一个或者多个 map 任务。
主要的决定因素有:input 的文件总个数,input 的文件大小,集群设置的文件块大小。
(2)是不是 map 数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小 128m),则每个小文件
也会被当做一个块,用一个 map 任务来完成,而一个 map 任务启动和初始化的时间远远大
于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的 map 数是受限的。
(3)是不是保证每个 map 处理接近 128m 的文件块,就高枕无忧了?
答案也是不一定。比如有一个 127m 的文件,正常会用一个 map 去完成,但这个文件只
有一个或者两个小字段,却有几千万的记录,如果 map 处理的逻辑比较复杂,用一个 map
任务去做,肯定也比较耗时。
针对上面的问题 2 和 3,我们需要采取两种方式来解决:即减少 map 数和增加 map 数;
6)小文件进行合并
在 Map 执行前合并小文件,减少 Map 数:CombineHiveInputFormat 具有对小文件进行
合并的功能(系统默认的格式)。HiveInputFormat 没有对小文件合并功能。
7)合理设置 Reduce 数
Reduce 个数并不是越多越好
(1)过多的启动和初始化 Reduce 也会消耗时间和资源;
(2)另外,有多少个 Reduce,就会有多少个输出文件,如果生成了很多个小文件,那
么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置 Reduce 个数的时候也需要考虑这两个原则:处理大数据量利用合适的 Reduce
数;使单个 Reduce 任务处理数据量大小要合适;
8)常用参数
// 输出合并小文件
SET hive.merge.mapfiles = true; – 默认 true,在 map-only 任务结束时合并
小文件
SET hive.merge.mapredfiles = true; – 默认 false,在 map-reduce 任务结
束时合并小文件
SET hive.merge.size.per.task = 268435456; – 默认 256M
SET hive.merge.smallfiles.avgsize = 16777216; – 当输出文件的平均大小
小于 16m 该值时,启动一个独立的 map-reduce 任务进行文件 merge
9)开启 map 端 combiner(不影响最终业务逻辑)
set hive.map.aggr=true;
10)压缩(选择快的)
设置 map 端输出、中间结果压缩。(不完全是解决数据倾斜的问题,但是减少了 IO 读
写和网络传输,能提高很多效率)
11)开启 JVM 重用
14.简述delete,drop,truncate的区别
delete 删除数据
drop 删除表
truncate 清空数据
15.四个by的区别
Sort By:分区内有序;sort by在每个reducer端都会做排序,为每个reduce产生一个排序文件。也就是说sort by能保证局部有序(每个reducer出来的数据是有序的,但是不能保证所有的数据是有序的,除非只有一个reducer)
Order By:全局排序,只有一个 Reducer;
Distrbute By:类似 MR 中 Partition,进行分区,结合 sort by 使用。DISTRIBUTE BY 是控制在map端如何拆分数据给reduce端的。hive会根据distribute by后面列,对应reduce的个数进行分发,默认是采用hash算法。
相同的将会分配到一个reducer.
Cluster By:当 Distribute by 和 Sorts by 字段相同时,可以使用 Cluster by 方式。Cluster by 除了具有Distribute by 的功能外还兼具 Sort by 的功能。但是排序只能是升序排序,不能 指定排序规则为 ASC 或者 DESC。
16.Hive里边字段的分隔符用的什么?为什么用\t?有遇到过字段里边有\t 的情况吗,怎么处理的?为什么不用Hive默认的分隔符,默认的分隔符是什么?
hive 默认的字段分隔符为 ascii 码的控制符\001(^A),建表的时候用 fields terminated by ‘\001’
遇到过字段里边有\t 的情况,自定义 InputFormat,替换为其他分隔符再做后续处理
17.分区分桶的区别,为什么要分区
分区表: 原来的一个大表存储的时候分成不同的数据目录进行存储。如果说是单分区表,那么在表的目录下就只有一级子目录,如果说是多分区表,那么在表的目录下有多少分区就有多少级子目录。不管是单分区表,还是多分区表,在表的目录下,和非最终分区目录下是不能直接存储数据文件的
分桶表: 原理和hashpartitioner 一样,将hive中的一张表的数据进行归纳分类的时候,归纳分类规则就是hashpartitioner。(需要指定分桶字段,指定分成多少桶)
分区表和分桶的区别除了存储的格式不同外,最主要的是作用:
- 分区表:细化数据管理,缩小mapreduce程序 需要扫描的数据量。
- 分桶表:提高join查询的效率,在一份数据会被经常用来做连接查询的时候建立分桶,分桶字段就是连接字段;提高采样的效率。
18.mapjoin的原理
MapJoin通常用于一个很小的表和一个大表进行join的场景,具体小表有多小,由参数hive.mapjoin.smalltable.filesize来决定,该参数表示小表的总大小,默认值为25000000字节,即25M。
Hive0.7之前,需要使用hint提示 /*+ mapjoin(table) */才会执行MapJoin,否则执行Common Join,但在0.7版本之后,默认自动会转换Map Join,由参数hive.auto.convert.join来控制,默认为true.
假设a表为一张大表,b为小表,并且hive.auto.convert.join=true,那么Hive在执行时候会自动转化为MapJoin。
1 | MapJoin简单说就是在Map阶段将小表读入内存,顺序扫描大表完成Join。减少昂贵的shuffle操作及reduce操作 |
19.在hive的row_number中distribute by 和 partition by的区别
distribute by + sort by = cluster by
partition by + order by : partition by 分组列 order by 排序列
Partition by
通常查询时会对整个数据库查询,而这带来了大量的开销,因此引入了partition的概念,在建表的时候通过设置partition的字段, 会根据该字段对数据分区存放,更具体的说是存放在不同的文件夹,这样通过指定设置Partition的字段条件查询时可以减少大量的开销
20.hive开发中遇到什么问题?
数据倾斜、调优
21.什么时候使用内部表,什么时候使用外部表
每天收集到的ng日志和埋点日志数据,需要做大量的统计数据分析,所以可以使用外部表进行存储,方便数据的共享,并且在对表做操作的时候不会误删原始数据。
在做统计分析时候用到的中间表,结果表可以使用内部表,因为这些数据不需要共享,使用内部表更为合适。并且很多时候分区表我们只需要保留最近3天的数据,用外部表的时候删除分区时无法删除数据。
22.hive都有哪些函数,你平常工作中用到哪些
数学函数
round(DOUBLE a)floor(DOUBLE a)
ceil(DOUBLE a)
rand()
集合函数
size(Map<K.V>)map_keys(Map<K.V>)
map_values(Map<K.V>)
array_contains(Array
, value) sort_array(Array
) 类型转换函数
cast(expr as) 日期函数
date_format函数(根据格式整理日期)
date_add、date_sub函数(加减日期)
next_day函数
last_day函数(求当月最后一天日期)
collect_set函数
get_json_object解析json函数from_unixtime(bigint unixtime, string format)
to_date(string timestamp)
year(string date)
month(string date)
hour(string date)
weekofyear(string date)
datediff(string enddate, string startdate)
add_months(string start_date, int num_months)
date_format(date/timestamp/string ts, string fmt)条件函数
if(boolean testCondition, T valueTrue, T valueFalseOrNull)nvl(T value, T default_value)
COALESCE(T v1, T v2, …)
CASE a WHEN b THEN c [WHEN d THEN e]* [ELSE f] END
isnull( a )
isnotnull ( a )
字符函数
concat(string|binary A, string|binary B…)concat_ws(string SEP, string A, string B…)
get_json_object(string json_string, string path)
length(string A)
lower(string A) lcase(string A)
parse_url(string urlString, string partToExtract [, string keyToExtract])
regexp_replace(string INITIAL_STRING, string PATTERN, string REPLACEMENT)
reverse(string A)
split(string str, string pat)
substr(string|binary A, int start) substring(string|binary A, int start)
聚合函数
count sum min max avg表生成函数
explode(arraya) explode(ARRAY)
json_tuple(jsonStr, k1, k2, …)
parse_url_tuple(url, p1, p2, …)