文章目录

  • 前言
  • 一、Hive
  • 1. Hive 表关联查询,如何解决数据倾斜的问题?
  • 2. 谈一下 Hive 的特点,Hive 和 RDBMS 有什么异同
  • 3. 请说明 hive 中 Sort By,Order By,Cluster By,Distrbute By各代表什么意思
  • 4. Hive 有哪些方式保存元数据,各有哪些特点
  • 5. Hive 内部表和外部表的区别
  • 6. Hive 的 HSQL 转换为 MapReduce 的过程
  • 7. Hive 中的压缩格式TextFile、SequenceFile、RCfile 、ORCfile各有什么区别
  • 8. Hive join 过程中大表小表的放置顺序
  • 9. 所有的Hive任务都会有MapReduce的执行吗
  • 10. Hive 的函数:UDF、UDAF、UDTF 的区别
  • 11. 说说对 Hive 桶表的理解
  • 12. Hive 自定义 UDF 函数的流程
  • 13. hive 有索引吗
  • 14. 数据建模用的哪些模型
  • 15. 为什么要对数据仓库分层
  • 二、Hive优化
  • 1. Fetch抓取
  • 2. 本地模式
  • 3. 表的优化
  • (1) 小表、大表join
  • (2) 大表Join小表
  • (3) Group By
  • 4. Count(Distinct) 去重统计
  • 5. 笛卡尔积
  • 6. 数据倾斜
  • (1) Map数
  • (2) 小文件进行合并
  • (3) 复杂文件增加Map数
  • (4) Reduce数
  • (5). 并行执行
  • 总结



前言

根据参考的各大面试题进行总结,并且不断更新。希望能帮助大家


一、Hive

1. 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。

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

Hive 和数据库除了拥有类似的查询语言,再无类似之处。

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

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

order by:会对输入做全局排序,因此只有一个 reducer(多个 reducer 无法保证全局有序)。只有一个 reducer,会导致当输入规模较大时,需要较长的计算时间。
sort by:不是全局排序,其在数据进入 reducer 前完成排序。
distribute by:按照指定的字段对数据进行划分输出到不同的 reduce 中。
cluster by:除了具有 distribute by 的功能外还兼具 sort by 的功能。

4. Hive 有哪些方式保存元数据,各有哪些特点

Hive 支持三种不同的元存储服务器,分别为:内嵌式元存储服务器、本地元存储服务器、远程元存储服务器,每种存储方式使用不同的配置参数。内嵌式元存储主要用于单元测试,在该模式下每次只有一个进程可以连接到元存储,Derby 是内嵌式元存储的默认数据库。在本地模式下,每个 Hive 客户端都会打开到数据存储的连接并在该连接上请求 SQL 查询。在远程模式下,所有的 Hive 客户端都将打开一个到元数据服务器的连接,该服务器依次查询元数据,元数据服务器和客户端之间使用 Thrift 协议通信。

5. Hive 内部表和外部表的区别

创建表时:创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径, 不对数据的位置做任何改变。
删除表时:在删除表的时候,内部表的元数据和数据会被一起删除, 而外部表只删除元数据,不删除数据。这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。

6. Hive 的 HSQL 转换为 MapReduce 的过程

hbase hive 面试 hive sql 面试_数据


过程描述如下:

SQL Parser:Antlr定义SQL的语法规则,完成SQL词法,语法解析,将SQL转化为抽象 语法树AST Tree

Semantic Analyzer:遍历AST Tree,抽象出查询的基本组成单元QueryBlock

Logical plan:遍历QueryBlock,翻译为执行操作树OperatorTree

Logical plan optimizer:逻辑层优化器进行OperatorTree变换,合并不必要的ReduceSinkOperator,减少shuffle数据量

Physical plan:遍历OperatorTree,翻译为MapReduce任务

Logical plan optimizer:物理层优化器进行MapReduce任务的变换,生成最终的执行计划。

7. 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
4)ORCFile
存储方式:数据按行分块 每块按照列存储
压缩快:快速列存取效率比rcfile高,是rcfile的改良版本。

总结:相比TEXTFILE和SEQUENCEFILE,RCFILE由于列式存储方式,数据加载时性能消耗较大,但是具有较好的压缩比和查询响应数据仓库的特点是一次写入、多次读取,因此,整体来看,RCFILE相比其余两种格式具有较明显的优势。

8. Hive join 过程中大表小表的放置顺序

将最大的表放置在 JOIN 语句的最右边,或者直接使用/*+ streamtable(table_name) */指出。在编写带有 join 操作的代码语句时,应该将条目少的表/子查询放在 Join 操作符的左边。因为在 Reduce 阶段,位于 Join 操作符左边的表的内容会被加载进内存,载入条目较少的表可以有效减少 OOM(out of memory)即内存溢出。所以对于同一个 key 来说,对应的 value 值小的放前,大的放后,这便是“小表放前”原则。若一条语句中有多个 Join,依据 Join 的条件相同与否,有不同的处理方法。

9. 所有的Hive任务都会有MapReduce的执行吗

不是,从Hive0.10.0版本开始,对于简单的不需要聚合的类似SELECT from
LIMIT n语句,不需要起MapReduce job,直接通过Fetch task获取数据。

10. Hive 的函数:UDF、UDAF、UDTF 的区别

UDF: 单行进入,单行输出
UDAF: 多行进入,单行输出
UDTF: 单行输入,多行输出

11. 说说对 Hive 桶表的理解

分区针对的是数据的存储路径;分桶针对的是数据文件。

Hive分桶通俗点来说就是将表(或者分区,也就是hdfs上的目录而真正的数据是存储在该目录下的文件)中文件分成几个文件去存储。比如表buck(目录,里面存放了某个文件如sz.data)文件中本来是1000000条数据,由于在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便,所以我们可以分4个文件去存储。

桶表是对数据进行哈希取值,然后放到不同文件中存储。数据加载到桶表时,会对字段取 hash 值,然后与桶的数量取模。把数据放到对应的文件中。物理上,每个桶就是表(或分区)目录里的一个文件,一个作业产生的桶(输出文件)和reduce 任务个数相同。桶表专门用于抽样查询,是很专业性的,不是日常用来存储数据的表,需要抽样查询时,才创建和使用桶表。

12. Hive 自定义 UDF 函数的流程

1)写一个类继承(org.apache.hadoop.hive.ql.)UDF 类;
2)覆盖方法 evaluate();
3)打 JAR 包;
4)通过 hive 命令将 JAR 添加到 Hive 的类路径:
hive> add jar /home/ubuntu/ToDate.jar;
5)注册函数:
hive> create temporary function xxx as ‘XXX’;
6)使用函数;

13. hive 有索引吗

Hive 支持索引,但是 Hive 的索引与关系型数据库中的索引并不相同,比如,Hive不支持主键或者外键。
Hive 索引可以建立在表中的某些列上,以提升一些操作的效率,例如减少
MapReduce 任务中需要读取的数据块的数量。在可以预见到分区数据非常庞大的情况下,索引常常是优于分区的。
虽然 Hive 并不像事物数据库那样针对个别的行来执行查询、更新、删除等操作。它更多的用在多任务节点的场景下,快速地全表扫描大规模数据。但是在某些场景下,建立索引还是可以提高 Hive 表指定列的查询速度。(虽然效果差强人意)
索引适用的场景
适用于不更新的静态字段。以免总是重建索引数据。每次建立、更新数据后,都要重建索引以构建索引表。

14. 数据建模用的哪些模型

星型模型
星形模式(Star Schema)是最常用的维度建模方式。星型模式是以事实表为中心,所有的维度表直接连接在事实表上,像星星一样。
星形模式的维度建模由一个事实表和一组维表成,且具有以下特点:
a. 维表只和事实表关联,维表之间没有关联;
b. 每个维表主键为单列,且该主键放置在事实表中,作为两边连接的外键;
c. 以事实表为核心,维表围绕核心呈星形分布;
雪花模型
雪花模式(Snowflake Schema)是对星形模式的扩展。雪花模式的维度表可以拥有其他维度表的,虽然这种模型相比星型更规范一些,但是由于这种模型不太容易理解,维护成本比较高,而且性能方面需要关联多层维表,性能也比星型模型要低。所以一般不是很常用。
星座模型
星座模式是星型模式延伸而来,星型模式是基于一张事实表的,而星座模式是基于多张事实表的,而且共享维度信息。前面介绍的两种维度建模方法都是多维表对应单事实表,但在很多时候维度空间内的事实表不止一个,而一个维表也可能被多个事实表用到。在业务发展后期,绝大部分维度建模都采用的是星座模式

15. 为什么要对数据仓库分层

  1. 用空间换时间,通过大量的预处理来提升应用系统的用户体验(效率),因此数据仓库会存在大量冗余的数据。
  2. 如果不分层的话,如果源业务系统的业务规则发生变化将会影响整个数据清洗过程,工作量巨大。
  3. 通过数据分层管理可以简化数据清洗的过程,因为把原来一步的工作分到了多个步骤去完成,相当于把一个复杂的工作拆成了多个简单的工作,把一个大的黑盒变成了一个白盒,每一层的处理逻辑都相对简单和容易理解,这样我们比较容易保证每一个步骤的正确性,当数据发生错误的时候,往往我们只需要局部调整某个步骤即可。

二、Hive优化

hive调优是比较大的专题,需要结合实际的业务,数据的类型,分布,质量状况等来实际的考虑如何进行系统性的优化,hive底层是mapreduce,所以hadoop调优也是hive调优的一个基础,hvie调优可以分为几个模块进行考虑,数据的压缩与存储,sql的优化,hive参数的优化,解决数据的倾斜等。

1. Fetch抓取

Fetch抓取是指,Hive中对某些情况的查询可以不必使用MapReduce计算。例如:SELECT * FROM
employees;在这种情况下,Hive可以简单地读取employee对应的存储目录下的文件,然后输出查询结果到控制台在hive-default.xml.template文件中hive.fetch.task.conversion默认是more,老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce

2. 本地模式

大多数的Hadoop Job是需要Hadoop提供的完整的可扩展性来处理大数据集的。不过,有时Hive的输入数据量是非常小的。在这种情况下,为查询触发执行任务时消耗可能会比实际job的执行时间要多的多。对于大多数这种情况,Hive可以通过本地模式在单台机器上处理所有的任务。对于小数据集,执行时间可以明显被缩短 。用户可以通过设置hive.exec.mode.local.auto的值为true,来让Hive在适当的时候自动启动这个优化

3. 表的优化

(1) 小表、大表join

将key相对分散,并且数据量小的表放在join的左边,这样可以有效减少内存溢出错误发生的几率;再进一步,可以使用Group让小的维度表(1000条以下的记录条数)先进内存。在map端完成reduce
实际测试发现:新版的hive已经对小表JOIN大表和大表JOIN小表进行了优化。小表放在左边和右边已经没有明显区别

(2) 大表Join小表

有时join超时是因为某些key对应的数据太多,而相同key对应的数据都会发送到相同的reducer上,从而导致内存不够。此时我们应该仔细分析这些异常的key,很多情况下,这些key对应的数据是异常数据,我们需要在SQL语句中进行过滤。例如key对应的字段为空

(3) 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中),最后完成最终的聚合操作 。

4. Count(Distinct) 去重统计

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

5. 笛卡尔积

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

6. 数据倾斜

(1) Map数

1)通常情况下,作业会通过input的目录产生一个或者多个map任务
主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小。
2)是不是map数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的
3)是不是保证每个map处理接近128m的文件块,就高枕无忧了?
答案也是不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时针对上面的问题2和3,我们需要采取两种方式来解决:即减少map数和增加map数

(2) 小文件进行合并

在map执行前合并小文件,减少map数:CombineHiveInputFormat具有对小文件进行合并的功能(系统默认的格式)。HiveInputFormat没有对小文件合并功能.

set hive.input.format= org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
(3) 复杂文件增加Map数

当input的文件都很大,任务逻辑复杂,map执行非常慢的时候,可以考虑增加Map数,来使得每个map处理的数据量减少,从而提高任务的执行效率 增加map的方法为:根据
computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M公式,调整maxSize最大值。让maxSize最大值低于blocksize就可以增加map的个数

(4) Reduce数

1)调整reduce个数方法一
(1)每个Reduce处理的数据量默认是256MB

hive.exec.reducers.bytes.per.reducer=256000000

(2)每个任务最大的reduce数,默认为1009

hive.exec.reducers.max=1009

(3)计算reducer数的公式
N=min(参数2,总输入数据量/参数1)

2)调整reduce个数方法二
在hadoop的mapred-default.xml文件中修改
设置每个job的Reduce个数

set mapreduce.job.reduces = 15;

3)reduce个数并不是越多越好
(1)过多的启动和初始化reduce也会消耗时间和资源;
(2)另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置reduce个数的时候也需要考虑这两个原则:处理大数据量利用合适的reduce数;使单个reduce任务处理数据量大小要合适。

(5). 并行执行

Hive会将一个查询转化成一个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段。或者Hive执行过程中可能需要的其他阶段。默认情况下,Hive一次只会执行一个阶段。不过,某个特定的job可能包含众多的阶段,而这些阶段可能并非完全互相依赖的,也就是说有些阶段是可以并行执行的,这样可能使得整个job的执行时间缩短。不过,如果有更多的阶段可以并行执行,那么job可能就越快完成
通过设置参数hive.exec.parallel值为true,就可以开启并发执行。不过,在共享集群中,需要注意下,如果job中并行阶段增多,那么集群利用率就会增加

set hive.exec.parallel=true;              //打开任务并行执行
set hive.exec.parallel.thread.number=16;  //同一个sql允许最大并行度,默认为8

当然,得是在系统资源比较空闲的时候才有优势,否则,没资源,并行也起不来

总结

持续更新…