写点什么

大数据培训 -Hive 高频面试题分享

作者:@零度
  • 2022 年 4 月 08 日
  • 本文字数:6688 字

    阅读完需:约 22 分钟

以下文章来源于大数据技术指南

一、Hive 面试题

1、hive 内部表和外部表的区别

未被 external 修饰的是内部表,被 external 修饰的为外部表。

区别:

内部表数据由 Hive 自身管理,外部表数据由 HDFS 管理;

内部表数据存储的位置是 hive.metastore.warehouse.dir(默认:/user/hive/warehouse), 外部表数据的存储位置由自己制定(如果没有 LOCATION,Hive 将在 HDFS 上 的/user/hive/warehouse 文件夹下以外部表的表名创建一个文件夹,并将属于这个表的数据存 放在这里);

删除内部表会直接删除元数据(metadata)及存储数据;删除外部表仅仅会删除元数据,HDFS 上的文件并不会被删除。

2、Hive 有索引吗

Hive 支持索引(3.0 版本之前),但是 Hive 的索引与关系型数据库中的索引并不相同。并且 Hive 索引提供的功能很有限,效率也并不高,因此 Hive 索引很少使用。

索引适用的场景:

适用于不更新的静态字段。以免总是重建索引数据。每次建立、更新数据后,都要重建索 引以构建索引表。

3、运维如何对 hive 进行调度

将 hive 的 sql 定义在脚本当中;

使用 azkaban 或者 oozie 进行任务的调度;

监控任务调度页面。

4、ORC、Parquet 等列式存储的优点

- ORC:ORC 文件是自描述的,它的元数据使用 Protocol Buffers 序列化,文件中的数据尽可能的压缩以降低存储空间的消耗;以二进制方式存储,不可以直接读取;自解析,包含许多元数据,这些元数据都是同构 ProtoBuffer 进行序列化的;会尽可能合并多个离散的区间尽可能的减少 I/O 次数;在新版本的 ORC 中也加入了对 Bloom Filter 的支持,它可以进一 步提升谓词下推的效率,在 Hive 1.2.0 版本以后也加入了对此的支持。

- Parquet:Parquet 支持嵌套的数据模型,类似于 Protocol Buffers,每一个数据模型的 schema 包含多个字段,每一个字段有三个属性:重复次数、数据类型和字段名;Parquet 中没有 Map、Array 这样的复杂数据结构,但是可以通过 repeated 和 group 组合来实现;通过 Striping/Assembly 算法,parquet 可以使用较少的存储空间表示复杂的嵌套格式,并且通常 Repetition level 和 Definition level 都是较小的整数值,可以通过 RLE 算法对其进行压缩,进一步降低存储空间;Parquet 文件以二进制方式存储,不可以直接读取和修改,Parquet 文件是自解析的,文件中包括该文件的数据和元数据。

5、数据建模用的哪些模型

  • 星型模型



星形模式(Star Schema)是最常用的维度建模方式。星型模式是以事实表为中心,所有的维度表直接连接在事实表上,像星星一样。星形模式的维度建模由一个事实表和一组维表成,且具有以下特点:

a. 维表只和事实表关联,维表之间没有关联;

b. 每个维表主键为单列,且该主键放置在事实表中,作为两边连接的外键;

c. 以事实表为核心,维表围绕核心呈星形分布。

  • 雪花模型



雪花模式(Snowflake Schema)是对星形模式的扩展。雪花模式的维度表可以拥有其他维度表的,虽然这种模型相比星型更规范一些,但是由于这种模型不太容易理解,维护成本比较高,而且性能方面需要关联多层维表,性能比星型模型要低_大数据培训

  • 星座模型



星座模式是星型模式延伸而来,星型模式是基于一张事实表的,而星座模式是基于多张事实表的,而且共享维度信息。前面介绍的两种维度建模方法都是多维表对应单事实表,但在很多时候维度空间内的事实表不止一个,而一个维表也可能被多个事实表用到。在业务发展后期,绝大部分维度建模都采用的是星座模式。

6、为什么要对数据仓库分层

用空间换时间,通过大量的预处理来提升应用系统的用户体验(效率),因此数据仓库会 存在大量冗余的数据。如果不分层的话,如果源业务系统的业务规则发生变化将会影响整个数据清洗过程,工作量巨大。

通过数据分层管理可以简化数据清洗的过程,因为把原来一步的工作分到了多个步骤去完成,相当于把一个复杂的工作拆成了多个简单的工作,把一个大的黑盒变成了一个白盒,每一层的处理逻辑都相对简单和容易理解,这样我们比较容易保证每一个步骤的正确性,当数据发生错误的时候,往往我们只需要局部调整某个步骤即可。

7、使用过 Hive 解析 JSON 串吗

Hive 处理 json 数据总体来说有两个方向的路走:

a.将 json 以字符串的方式整个入 Hive 表,然后通过使用 UDF 函数解析已经导入到 hive 中的数据,比如使用 LATERAL VIEW json_tuple 的方法,获取所需要的列名。

b.在导入之前将 json 拆成各个字段,导入 Hive 表的数据是已经解析过的。这将需要使用第三方的 SerDe。

8、sort by 和 order by 的区别

order by 会对输入做全局排序,因此只有一个 reducer(多个 reducer 无法保证全局有序)只有一个 reducer,会导致当输入规模较大时,需要较长的计算时间。

sort by 不是全局排序,其在数据进入 reducer 前完成排序. 因此,如果用 sort by 进行排序,并且设置 mapred.reduce.tasks>1, 则 sort by 只保证每个 reducer 的输出有序,不保证全局有序。

9、数据倾斜怎么解决

  • 空值引发的数据倾斜

  • 解决方案:

  • 第一种:可以直接不让 null 值参与 join 操作,即不让 null 值有 shuffle 阶段

  • 第二种:因为 null 值参与 shuffle 时的 hash 结果是一样的,那么我们可以给 null 值随机赋值,这样它们的 hash 结果就不一样,就会进到不同的 reduce 中

  • 不同数据类型引发的数据倾斜

  • 解决方案:

  • 如果 key 字段既有 string 类型也有 int 类型,默认的 hash 就都会按 int 类型来分配,那我们直接把 int 类型都转为 string 就好了,这样 key 字段都为 string,hash 时就按照 string 类型分配了

  • 不可拆分大文件引发的数据倾斜

  • 解决方案:

  • 这种数据倾斜问题没有什么好的解决方案,只能将使用 GZIP 压缩等不支持文件分割的文件转为 bzip 和 zip 等支持文件分割的压缩方式。

  • 所以,我们在对文件进行压缩时,为避免因不可拆分大文件而引发数据读取的倾斜,在数据压缩的时候可以采用 bzip2 和 Zip 等支持文件分割的压缩算法。

  • 数据膨胀引发的数据倾斜

  • 解决方案:

  • 在 Hive 中可以通过参数 hive.new.job.grouping.set.cardinality 配置的方式自动控制作业的拆解,该参数默认值是 30。表示针对 grouping sets/rollups/cubes 这类多维聚合的操作,如果最后拆解的键组合大于该值,会启用新的任务去处理大于该值之外的组合。如果在处理数据时,某个分组聚合的列有较大的倾斜,可以适当调小该值。

  • 表连接时引发的数据倾斜

  • 解决方案:

  • 通常做法是将倾斜的数据存到分布式缓存中,分发到各个 Map 任务所在节点。在 Map 阶段完成 join 操作,即 MapJoin,这避免了 Shuffle,从而避免了数据倾斜。

  • 确实无法减少数据量引发的数据倾斜

  • 解决方案:

  • 这类问题最直接的方式就是调整 reduce 所执行的内存大小。

  • 调整 reduce 的内存大小使用 mapreduce.reduce.memory.mb 这个配置。

10、Hive 小文件过多怎么解决

使用 hive 自带的 concatenate 命令,自动合并小文件

调整参数减少 Map 数量

减少 Reduce 的数量

使用 hadoop 的 archive 将小文件归档

11、Hive 优化有哪些

数据存储及压缩

通过调参优化

有效地减小数据集将大表拆分成子表;结合使用外部表和分区表

SQL 优化

二、Hive 高频面试点集合

1、Hive 的两张表关联,使用 MapReduce 怎么实现?

如果其中有一张表为小表,直接使用 map 端 join 的方式(map 端加载小表)进行聚合。

如果两张都是大表,那么采用联合 key,联合 key 的第一个组成部分是 join on 中的公共字段,第二部分是一个 flag,0 代表表 A,1 代表表 B,由此让 Reduce 区分客户信息和订单信息;在 Mapper 中同时处理两张表的信息,将 join on 公共字段相同的数据划分到同一个分区中,进而传递到一个 Reduce 中,然后在 Reduce 中实现聚合。

2、请谈一下 Hive 的特点,Hive 和 RDBMS 有什么异同?

hive 是基于 Hadoop 的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供完整的 sql 查询功能,可以将 sql 语句转换为 MapReduce 任务进行运行。其优点是学习成本低,可以通过类 SQL 语句快速实现简单的 MapReduce 统计,不必开发专门的 MapReduce 应用,十分适合数据仓库的统计分析,但是 Hive 不支持实时查询。

Hive 与关系型数据库的区别:



3、请说明 hive 中 Sort By,Order By,Cluster By,Distrbute By 各代表什么意思?

Order by:会对输入做全局排序,因此只有一个 reducer(多个 reducer 无法保证全局有序)。只有一个 reducer,会导致当输入规模较大时,需要较长的计算时间。

Sort by:不是全局排序,其在数据进入 reducer 前完成排序。1

Distribute by:按照指定的字段对数据进行划分输出到不同的 reduce 中。

Cluster by:除了具有 distribute by 的功能外还兼具 sort by 的功能。

4、写出 Hive 中 split、coalesce 及 collect_list 函数的用法(可举例)?

split 将字符串转化为数组,即:split('a,b,c,d' , ',') ==> ["a","b","c","d"]。

coalesce(T v1, T v2, …) 返回参数中的第一个非空值;如果所有值都为 NULL,那么返回 NULL。

collect_list 列出该字段所有的值,不去重 => select collect_list(id) from table。

5、 Hive 有哪些方式保存元数据,各有哪些特点?

Hive 支持三种不同的元存储服务器,分别为:内嵌式元存储服务器、本地元存储服务器、远程元存储服务器,每种存储方式使用不同的配置参数。

内嵌式元存储主要用于单元测试,在该模式下每次只有一个进程可以连接到元存储,Derby 是内嵌式元存储的默认数据库。

在本地模式下,每个 Hive 客户端都会打开到数据存储的连接并在该连接上请求 SQL 查询。

在远程模式下,所有的 Hive 客户端都将打开一个到元数据服务器的连接,该服务器依次查询元数据,元数据服务器和客户端之间使用 Thrift 协议通信。

6、Hive 内部表和外部表的区别?

创建表时:创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。

删除表时:在删除表的时候,内部表的元数据和数据会被一起删除, 而外部表只删除元数据,不删除数据。这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。

7、Hive 的函数:UDF、UDAF、UDTF 的区别?

UDF:单行进入,单行输出

UDAF:多行进入,单行输出

UDTF:单行输入,多行输出

8、所有的 Hive 任务都会有 MapReduce 的执行吗?

不是,从 Hive0.10.0 版本开始,对于简单的不需要聚合的类似 SELECT from

LIMIT n 语句,不需要起 MapReduce job,直接通过 Fetch task 获取数据。

9、说说对 Hive 桶表的理解?

桶表是对数据某个字段进行哈希取值,然后放到不同文件中存储。

数据加载到桶表时,会对字段取 hash 值,然后与桶的数量取模。把数据放到对应的文件中。物理上,每个桶就是表(或分区)目录里的一个文件,一个作业产生的桶(输出文件)和 reduce 任务个数相同。

桶表专门用于抽样查询,是很专业性的,不是日常用来存储数据的表,需要抽样查询时,才创建和使用桶表。



12、Hive 中的压缩格式 TextFile、SequenceFile、RCfile 、ORCfile 各有什么区别?

1、TextFile

默认格式,存储方式为行存储,数据不做压缩,磁盘开销大,数据解析开销大。可结合 Gzip、Bzip2 使用(系统自动检查,执行查询时自动解压),但使用这种方式,压缩后的文件不支持 split,Hive 不会对数据进行切分,从而无法对数据进行并行操作。并且在反序列化过程中,必须逐个字符判断是不是分隔符和行结束符,因此反序列化开销会比 SequenceFile 高几十倍。

2、SequenceFile

SequenceFile 是 Hadoop API 提供的一种二进制文件支持,存储方式为行存储,其具有使用方便、可分割、可压缩的特点。

SequenceFile 支持三种压缩选择:NONE,RECORD,BLOCK。Record 压缩率低,一般建议使用 BLOCK 压缩。

优势是文件和 hadoop api 中的 MapFile 是相互兼容的

3、RCFile

存储方式:数据按行分块,每块按列存储。结合了行存储和列存储的优点:

首先,RCFile 保证同一行的数据位于同一节点,因此元组重构的开销很低;

其次,像列存储一样,RCFile 能够利用列维度的数据压缩,并且能跳过不必要的列读取;

4、ORCFile

存储方式:数据按行分块 每块按照列存储。

压缩快、快速列存取。

效率比 rcfile 高,是 rcfile 的改良版本。

小结:

相比 TEXTFILE 和 SEQUENCEFILE,RCFILE 由于列式存储方式,数据加载时性能消耗较大,但是具有较好的压缩比和查询响应。

数据仓库的特点是一次写入、多次读取,因此,整体来看,RCFILE 相比其余两种格式具有较明显的优势。

13、Hive 表关联查询,如何解决数据倾斜的问题?

1)倾斜原因:map 输出数据按 key Hash 的分配到 reduce 中,由于 key 分布不均匀、业务数据本身的特、建表时考虑不周、等原因造成的 reduce 上的数据量差异过大。(1)key 分布不均匀; (2)业务数据本身的特性; (3)建表时考虑不周; (4)某些 SQL 语句本身就有数据倾斜;

如何避免:对于 key 为空产生的数据倾斜,可以对其赋予一个随机值。

2)解决方案

(1)参数调节:    hive.map.aggr = true     hive.groupby.skewindata=true

有数据倾斜的时候进行负载均衡,当选项设定位 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。

(2)SQL 语句调节:

  ① 选用 join key 分布最均匀的表作为驱动表。做好列裁剪和 filter 操作,以达到两表做 join 的时候,数据量相对变小的效果。  ② 大小表 Join:    使用 map join 让小的维度表(1000 条以下的记录条数)先进内存。在 map 端完成 reduce。  ③ 大表 Join 大表:    把空值的 key 变成一个字符串加上随机数,把倾斜的数据分到不同的 reduce 上,由于 null 值关联不上,处理后并不影响最终结果。  ④ count distinct 大量相同特殊值:     count distinct 时,将值为空的情况单独处理,如果是计算 count distinct,可以不用处理,直接过滤,在最后结果中加 1。如果还有其他计算,需要进行 group by,可以先将值为空的记录单独处理,再和其他计算结果进行 union。

14、Fetch 抓取

Fetch 抓取是指,Hive 中对某些情况的查询可以不必使用 MapReduce 计算。例如:SELECT * FROM employees;在这种情况下,Hive 可以简单地读取 employee 对应的存储目录下的文件,然后输出查询结果到控制台。

在 hive-default.xml.template 文件中 hive.fetch.task.conversion 默认是 more,老版本 hive 默认是 minimal,该属性修改为 more 以后,在全局查找、字段查找、limit 查找等都不走 mapreduce。

15、小表、大表 Join

将 key 相对分散,并且数据量小的表放在 join 的左边,这样可以有效减少内存溢出错误发生的几率;再进一步,可以使用 Group 让小的维度表(1000 条以下的记录条数)先进内存。在 map 端完成 reduce。

实际测试发现:新版的 hive 已经对小表 JOIN 大表和大表 JOIN 小表进行了优化。小表放在左边和右边已经没有明显区别。

16、大表 Join 大表

1)空 KEY 过滤   有时 join 超时是因为某些 key 对应的数据太多,而相同 key 对应的数据都会发送到相同的 reducer 上,从而导致内存不够。此时我们应该仔细分析这些异常的 key,很多情况下,这些 key 对应的数据是异常数据,我们需要在 SQL 语句中进行过滤。例如 key 对应的字段为空。2)空 key 转换   有时虽然某个 key 为空对应的数据很多,但是相应的数据不是异常数据,必须要包含在 join 的结果中,此时我们可以表 a 中 key 为空的字段赋一个随机的值,使得数据随机均匀地分不到不同的 reducer 上。

17、Group By

默认情况下,Map 阶段同一 Key 数据分发给一个 reduce,当一个 key 数据过大时就倾斜了。

并不是所有的聚合操作都需要在 Reduce 端完成,很多聚合操作都可以先在 Map 端进行部分聚合,最后在 Reduce 端得出最终结果。1)开启 Map 端聚合参数设置     (1)是否在 Map 端进行聚合,默认为 True       hive.map.aggr = true     (2)在 Map 端进行聚合操作的条目数目       hive.groupby.mapaggr.checkinterval = 100000     (3)有数据倾斜的时候进行负载均衡(默认是 false)       hive.groupby.skewindata = true

当选项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;

第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。

18、Count(Distinct) 去重统计

数据量小的时候无所谓,数据量大的情况下,由于 COUNT DISTINCT 操作需要用一个 Reduce Task 来完成,这一个 Reduce 需要处理的数据量太大,就会导致整个 Job 很难完成,一般 COUNT DISTINCT 使用先 GROUP BY 再 COUNT 的方式替换

尽量避免笛卡尔积,join 的时候不加 on 条件,或者无效的 on 条件,Hive 只能使用 1 个 reducer 来完成笛卡尔积

用户头像

@零度

关注

关注尚硅谷,轻松学IT 2021.11.23 加入

IT培训 www.atguigu.com

评论

发布
暂无评论
大数据培训-Hive高频面试题分享_hive_@零度_InfoQ写作平台