hive面试题汇总

1. Hive和数据库比较

Hive 和数据库除了拥有类似的查询语言,再无类似之处。
1)数据存储位置
Hive 存储在 HDFS 。数据库将数据保存在块设备或者本地文件系统中。
2)数据更新
Hive中不建议对数据的改写。而数据库中的数据通常是需要经常进行修改的,
3)执行延迟
Hive 执行延迟较高。数据库的执行延迟较低。当然,这个是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。
4)数据规模
Hive支持很大规模的数据计算;数据库可以支持的数据规模较小。

2. 内部表和外部表

1)管理表:当我们删除一个管理表时,Hive也会删除这个表中数据。管理表不适合和其他工具共享数据。
2)外部表:删除该表并不会删除掉原始数据,删除的是表的元数据

3. 4个By区别

1)Sort By:分区内有序;
2)Order By:全局排序,只有一个Reducer;
3)Distrbute By:类似MR中Partition,进行分区,结合sort by使用。
4) Cluster By:当Distribute by和Sorts by字段相同时,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外还兼具Sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。

4. 窗口函数

RANK() 排序相同时会重复,总数不会变
DENSE_RANK() 排序相同时会重复,总数会减少
ROW_NUMBER() 会根据顺序计算
1) OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变而变化
2)CURRENT ROW:当前行
3)n PRECEDING:往前n行数据
4) n FOLLOWING:往后n行数据
5)UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING表示到后面的终点
6) LAG(col,n):往前第n行数据
7)LEAD(col,n):往后第n行数据
8) NTILE(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。注意:n必须为int类型。

5. 自定义UDF、UDTF

在项目中是否自定义过UDF、UDTF函数,以及用他们处理了什么问题,及自定义步骤?
1)自定义过。
2)用UDF函数解析公共字段;用UDTF函数解析事件字段。
自定义UDF:继承UDF,重写evaluate方法
自定义UDTF:继承自GenericUDTF,重写3个方法:initialize(自定义输出的列名和类型),process(将结果返回forward(result)),close
为什么要自定义UDF/UDTF,因为自定义函数,可以自己埋点Log打印日志,出错或者数据异常,方便调试.

6. 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; – 当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge

7.Hive的SQL语句如何转换为MR任务?

在这里插入图片描述

  1. 先通过SQLParser解析器对SQL语句进行解析
  2. 再通过PhysicalPlan编译器对其进行编译
  3. 通过QueryPotimizer优化对其进行优化
  4. 最后通过Execution执行器生成MR任务,进行运行

8.几种join的区别

inner join:只有连接的两个表中都存在与连接标准相匹配的数据才会保留下来
left outer join:左边表全返回,右边表没匹配的返回null
right outer join:同上
full outer join:(完全外连接)会返回所有表中符合where筛选条件的记录
left semi join:(左半开连接)返回左表的记录,其记录对于右表满足on的筛选条件(可替代in)
cross join(不指定连接条件的join):笛卡尔积join
map join:小表join大表,小表在左边,大表右边,将小表读入内存,在map端join大表,省略reduce

9.drop delete turncate区别

drop:删除整个表数据及表定义
delete:可以有条件的删除(delete from 表名 where)数据,保留表结构
truncate:删除所有数据

10.where和having有什么区别

where:是一个约束声明,在对查询结果进行分组前先筛选数据,条件中不能包含聚合函数,作用在group by和having前
having:是一个过滤声明,是在查询返回结果集之后对结果进行的过滤操作,筛选分组的数据

11.select、from、where、group by、order by在一个Hive语句中,这些执行的顺序

from–>on–>join–>where–>group by–>having–>select -->distinct–>union–>order by–>limit

12.分区和分桶具体怎么实现的,有什么区别

分区是对数据表中的某列或某些列进行划分,划分为多个区,形式上可以理解为文件夹
分桶是对分区来说更细粒度的划分,通过对某列计算hash,通过计算结果进行分桶

分区:将数据从物理上转移到和使用最频繁的用户更近的地方,分区表改变了hive对数据存储的组织方式,warehouse/数据库/表名 —> warehouse/数据库/表名/dt=2020 ,分区后hive将创建可以反映分区结构的子目录,dt的值已经包含在目录名称中了,所以没必要将其存放在目录下的文件中。

分桶:指定分桶表的某一列,让该列数据按照哈希取模的方式随机、均匀地分发到各个桶文件中。因为分桶改变了数据的存储方式,它会把哈希取模相同或者在某一区间的数据行放在同一个桶文件中。提高查询效率(对两张在同一列上进行了分桶操作的表进行JOIN操作的时候,只需要对保存相同列值的桶进行JOIN操作即可)

建表语句: create table ... cluster by user_id into 96 buckets 

插入时set hive.enforce.bucketing=true强制hive为目标分桶表设置正确的reducer数,如果不指定,需要自己设置正确的reducer数:set mapred.reduce.tasks=96

13.Hive的map/reduce数怎么确定

map

map数没有办法直接设置,主要决定因素为:输入文件的数量、大小,集群设置的文件块的大小。

调整map数的几个参数:

set mapred.max.split.size=100000000(决定每个map处理的最大的文件大小)
set mapred.min.split.size.per.node=100000000(一个节点上split的至少的大小(这个值决定了多个DataNode上的文件是否需要合并))
set mapred.min.split.size.per.rack=100000000(一个交换机下split的至少的大小(这个值决定了多个交换机上的文件是否需要合并))

reduce

不指定的话,默认的计算方式为:
min(每个任务最大的reduce数,总输入数据量/每个reduce任务处理的数据量)

调整reduce数的几个参数:

hive.exec.reducers.bytes.per.reducer(每个reduce任务处理的数据量)
mapred.reduce.tasks (设置reduce的数量)
hive.merge.mapredfiles(reduce端小文件合并)

14.如何判断数据倾斜及解决方法

数据倾斜的表现

  1. MapReduce:reduce阶段卡住,如一直卡在99.9%,查看日志或监控页面显示:有一个多几个reduce卡住,各种container报错OOM,读写的数据量极大,至少远远超过其它正常的reduce,伴随着数据倾斜,还可以通过任务的counter判断,倾斜的task的counter特别大,输出字符数特别多
  2. Spark:Executor lost,OOM,Shuffle过程出错,Driver OOM,单个Executor执行时间特别久,整体任务卡在某个阶段不能结束

可能造成数据倾斜的几个原因

  1. 数据的key分化严重不均,某一个key的条数比其他key多很多,这条key所在的reduce节点所处理的数据量比其他节点就大很多,造成一部分数据很多,一部分数据很少的局面
  2. 配置不合理、业务逻辑不合理
  3. group by 维度过小,某值的数过多 后果:处理某值的reduce非常耗时
  4. count distinct某特殊值过多 后果:处理此特殊值的reduce耗时,distinct会把所有数据shuffle到一个reducer中,group by 会把数据分布到多台机器上执行
  5. join,大表与大表,空值过多,结果空值都到一个reducer中进行处理
  6. 不同数据类型进行关联产生倾斜,一个ID为int,另一个表中ID有的为int,有的为string,进行join时会按int来hash,导致所有的string类型都分到一个reducer中

数据倾斜的解决方法

解决 group by 造成的数据倾斜

  1. hive.map.aggr=true:在map中会做部分聚集操作,效率更高但需要更多的内存
  2. hive.groupby.skewindata=true:数据倾斜时负载均衡
  3. 对count distinct,将值为空的情况单独处理,或使用子查询,先group by ,再count*

解决 join 造成的数据倾斜

  1. hive.optimize.skewjoin = true
  2. 如果有小表参与 join 操作,使用 map join
  3. 把特殊值select出来单独做join,不特殊的再一起join,最后结果union
  4. 谓词下推:尽早进行过滤,减少后续处理的数据量
  5. 把空值改一个随机数,如111,222(可解决大表join大表时的空key倾斜)

13.Hive中小文件相关问题

小文件是如何产生的

  1. 动态分区插入数据,产生大量的小文件,从而导致map数量剧增
  2. reduce数量越多,小文件也越多
  3. 数据源本身就包含大量的小文件

小文件的影响

  1. 小文件会开很多map,一个map开一个JVM去执行,所以这些任务的初始化,启动,执行会浪费大量的资源,严重影响性能
  2. HDFS中,小文件过多会占用大量内存,NameNode内存容量严重制约了集群的扩展
  3. HDFS读写小文件更加耗时,每次都需要从 NN 获取元信息,并与对应的DataNode建立连接。

小文件的解决方案

  1. 设置合并参数:
是否合并Map输出文件:hive.merge.mapfiles=true(默认值为真)
是否合并Reduce 端输出文件:hive.merge.mapredfiles=false(默认值为假)
合并文件的大小:hive.merge.size.per.task=256
  1. 少使用textfile;
  2. 少用动态分区;
  3. 设置reduce数量

对于已有的小文件的解决方案

  1. Hadoop archive命令进行归档(har命令);
  2. 重跑数据,指定map reduce参数,指定存储格式(ORC)

14.行转列与列转行

行转列:explode,一般结合侧视图使用
列转行:collect_set、collect_list(set去重、list不去重)

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值