hive面试题超详细-一站式搞定面试

本文详述了Hive解决数据倾斜的各种方法,包括单表group by、JOIN ON关联字段的优化策略。同时探讨了Hive的缺点、作用及其与数据库的区别。深入讲解了Hive的存储格式如ORC和Parquet的优势,以及内部表和外部表的区别。此外,还涵盖了分区表、分桶表、Hive索引、数据建模和SQL优化等内容,全方位解析Hive在数据仓库中的调优实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hive

9 Hive解决数据倾斜方法

1)数据倾斜长啥样?

task执行时间远比其他task运行时间大,或者reduce阶段卡在99%

2) 单表 – group by id

​ (1) 按照id分组计算count值

​ -> 单个Key

​ -> 多个Key

​ (2) 单个Key

​ 加随机数,双重聚合

​ 配置参数,双重聚合 set hive.groupby.skewindata = true;

​ 过滤出这个Key单独处理

​ (3) 多个Key

​ 增加Reducer个数,一定程度上解决问题

​ 自定义分区器

​ 加随机数,双重聚合

​ 配置参数,双重聚合 set hive.groupby.skewindata = true;

3) JOIN ON 关联字段

​ (1) 大表JOIN小表 mapJoin 避免了Reducer

​ (2) 大表JOIN大表 A表加随机数 B表扩容 聚合

​ A concat(id,‘_’,随机数[1,2,3])

​ B

​ concat(id,‘_’,1)

​ union all

​ concat(id,‘_’,2)

​ union all

​ concat(id,‘_’,3)

hive缺点

  1. Hive的HQL表达能力有限迭代式算法无法表达

数据挖掘方面不擅长,由于MapReduce数据处理流程的限制,效率更高的算法却无法实现。

  1. Hive的效率比较低

Hive自动生成的MapReduce作业,通常情况下不够智能化Hive调优比较困难,粒度较粗

Hive不是一个完整的数据库。Hadoop以及HDFS的设计本身约束和局限性地限制了Hive所能胜任的工

作。其中最大的限制就是Hive不支持记录级别的更新、插入或者删除操作。但是用户可以通过查询生成 新表或者将查询结果导入到文件中。同时,因为Hadoop是面向批处理的系统,而MapReduce任务

(job)的启动过程需要消耗较长的时间,所以Hive查询延时比较严重。传统数据库中在秒级别可以完成 的查询,在Hive中,即使数据集相对较小,往往也需要执行更长的时间。

3、Hive的作用

Hive是由Facebook开源用于解决海量结构化日志的数据统计工具。可以将结构化的数据文件映射为一张表,并提供类SQL查询功能。

Hive的本质是将HQL转化成MapReduce程序

Hive处理的数据存储在HDFS

Hive分析数据底层的实现是MapReduce

执行程序运行在Yarn上

1.Hive架构体系

img

  1. 用户接口:client

CLI(command-line interface)、JDBC/ODBC(jdbc 访问 hive)、WEBUI(浏览器访问 hive)

  1. 元数据:Metastore

元数据包括:表名、表所属的数据库(默认是 default)、表的拥有者、列/分区字段、 表的类型(是否是外部表)、表的数据所在目录等;

默认存储在自带的 derby 数据库中,推荐使用 MySQL 存储 Metastore。

  1. Hadoop

使用 HDFS 进行存储,使用 MapReduce 进行计算。

  1. 驱动器:Driver

    1. 解析器(SQL Parser):将 SQL 字符串转换成抽象语法树 AST,这一步一般都用第三方工具库完成,比如 antlr;对 AST 进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误。
    2. 编译器(Physical Plan):将 AST 编译生成逻辑执行计划。
    3. 优化器(Query Optimizer):对逻辑执行计划进行优化。
    4. 执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。对于 Hive 来说,就是 MR/Spark。

img

Hive 通过给用户提供的一系列交互接口,接收到用户的指令(SQL),使用自己的 Driver,结合元数据(MetaStore),将这些指令翻译成 MapReduce,提交到 Hadoop 中执行,最后,将执行返回的结果输出到用户交互接口。

2.Hive与数据库的区别

由于 Hive 采用了类似 SQL 的查询语言 HQL(Hive Query Language),因此很容易将 Hive 理解为数据库。其实从结构上来看,Hive 和数据库除了拥有类似的查询语言,再无类似之处。本文将从多个方面来阐述 Hive 和数据库的差异。数据库可以用在 Online 的应用中,但是 Hive 是为数据仓库而设计的,清楚这一点,有助于从应用角度理解 Hive 的特性。

2.1 查询语言

由于 SQL 被广泛的应用在数据仓库中,因此,专门针对 Hive 的特性设计了类 SQL 的查询语言 HQL。熟悉 SQL 开发的开发者可以很方便的使用 Hive 进行开发。

2.2 数据更新

由于 Hive 是针对数据仓库应用设计的,而数据仓库的内容是读多写少的。因此,Hive 中不建议对数据的改写,所有的数据都是在加载的时候确定好的。而数据库中的数据通常是需要经常进行修改的,因此可以使用 INSERT INTO … VALUES 添加数据,使用 UPDATE … SET 修改数据。

2.3 执行延迟

Hive 在查询数据的时候,由于没有索引,需要扫描整个表,因此延迟较高。另外一个导致 Hive 执行延迟高的因素是 MapReduce 框架。由于 MapReduce 本身具有较高的延迟,因此在利用 MapReduce 执行 Hive 查询时,也会有较高的延迟。相对的,数据库的执行延迟较低。当然,这个低是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive 的并行计算显然能体现出优势。

2.4 数据规模

由于 Hive 建立在集群上并可以利用 MapReduce 进行并行计算,因此可以支持很大规模的数据;对应的,数据库可以支持的数据规模较小。

3.文件存储格式(行式存储和列式存储)

Hive 支持的存储数据的格式主要有:TEXTFILE 、SEQUENCEFILE、ORC、PARQUET。

TEXTFILE 和 SEQUENCEFILE 的存储格式都是基于行存储的;

ORC 和 PARQUET 是基于列式存储的。

img

  1. 行存储的特点

查询满足条件的一整行数据的时候,列存储则需要去每个聚集的字段找到对应的每个列的值,行存储只需要找到其中一个值,其余的值都在相邻地方,所以此时行存储查询的速度更快。

  1. 列存储的特点

因为每个字段的数据聚集存储,在查询只需要少数几个字段的时候,能大大减少读取的数据量;每个字段的数据类型一定是相同的,列式存储可以针对性的设计更好的设计压缩算法。

3.1 ORC

如下图所示可以看到每个Orc文件由1个或多个 stripe 组成,每个stripe一般为 HDFS的块大小,每一个 stripe 包含多条记录,这些记录按照列进行独立存储,对应到Parquet中的row group的概念。每个Stripe里有三部分组成,分别是Index Data,Row Data,Stripe Footer:

img

  1. Index Data:一个轻量级的 index,默认是每隔 1W 行做一个索引。这里做的索引应该 只是记录某行的各字段在 Row Data 中的 offset。
  2. Row Data:存的是具体的数据,先取部分行,然后对这些行按列进行存储。对每个列进行了编码,分成多个 Stream 来存储。
  3. Stripe Footer:存的是各个 Stream 的类型,长度等信息。每个文件有一个 File Footer,这里面存的是每个 Stripe 的行数,每个 Column 的数据类型信息等;每个文件的尾部是一个 PostScript,这里面记录了整个文件的压缩类型以及FileFooter 的长度信息等。在读取文件时,会 seek 到文件尾部读 PostScript,从里面解析到File Footer 长度,再读 FileFooter,从里面解析到各个 Stripe 信息,再读各个 Stripe,即从后往前读。

3.2 Parquet

Parquet 文件是以二进制方式存储的,所以是不可以直接读取的,文件中包括该文件的数据和元数据,因此 Parquet 格式文件是自解析的。

  1. 行组(Row Group):每一个行组包含一定的行数,在一个 HDFS 文件中至少存储一个行组,类似于 orc 的 stripe 的概念。
  2. 列块(Column Chunk):在一个行组中每一列保存在一个列块中,行组中的所有列连续的存储在这个行组文件中。一个列块中的值都是相同类型的,不同的列块可能使用不同的算法进行压缩。
  3. 页(Page):每一个列块划分为多个页,一个页是最小的编码的单位,在同一个列块的不同页可能使用不同的编码方式。通常情况下,在存储 Parquet 数据的时候会按照 Block 大小设置行组的大小,由于一般情况下每一个 Mapper 任务处理数据的最小单位是一个 Block,这样可以把每一个行组由一个 Mapper 任务处理,增大任务执行并行度。

img

上图展示了一个 Parquet 文件的内容,一个文件中可以存储多个行组,文件的首位都是该文件的 Magic Code,用于校验它是否是一个 Parquet 文件,Footer length 记录了文件元数据的大小,通过该值和文件长度可以计算出元数据的偏移量,文件的元数据中包括每一个行组的元数据信息和该文件存储数据的 Schema 信息。除了文件中每一个行组的元数据,每一页的开始都会存储该页的元数据,在 Parquet 中,有三种类型的页:数据页、字典页和索引页。数据页用于存储当前行组中该列的值,字典页存储该列值的编码字典,每一个列块中最多包含一个字典页,索引页用来存储当前行组下该列的索引,目前 Parquet 中还不支持索引页。

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

ORC和Parquet都是高性能的存储方式,这两种存储格式总会带来存储和性能上的提升。

Parquet:

  1. Parquet支持嵌套的数据模型,类似于Protocol Buffers,每一个数据模型的schema包含多个字段,每一个字段有三个属性:重复次数、数据类型和字段名。
    重复次数可以是以下三种:required(只出现1次),repeated(出现0次或多次),optional(出现0次或1次)。每一个字段的数据类型可以分成两种: group(复杂类型)和primitive(基本类型)。
  2. Parquet中没有Map、Array这样的复杂数据结构,但是可以通过repeated和group组合来实现的。
  3. 由于Parquet支持的数据模型比较松散,可能一条记录中存在比较深的嵌套关系,如果为每一条记录都维护一个类似的树状结可能会占用较大的存储空间,因此Dremel论文中提出了一种高效的对于嵌套数据格式的压缩算法:Striping/Assembly算法。通过Striping/Assembly算法,parquet可以使用较少的存储空间表示复杂的嵌套格式,并且通常Repetition level和Definition level都是较小的整数值,可以通过RLE算法对其进行压缩,进一步降低存储空间。
  4. Parquet文件是以二进制方式存储的,是不可以直接读取和修改的,Parquet文件是自解析的,文件中包括该文件的数据和元数据。

ORC:

  1. ORC文件是自描述的,它的元数据使用Protocol Buffers序列化,并且文件中的数据尽可能的压缩以降低存储空间的消耗。
  2. 和Parquet类似,ORC文件也是以二进制方式存储的,所以是不可以直接读取,ORC文件也是自解析的,它包含许多的元数据,这些元数据都是同构ProtoBuffer进行序列化的。
  3. ORC会尽可能合并多个离散的区间尽可能的减少I/O次数。
  4. ORC中使用了更加精确的索引信息,使得在读取数据时可以指定从任意一行开始读取,更细粒度的统计信息使得读取ORC文件跳过整个row group,ORC默认会对任何一块数据和索引信息使用ZLIB压缩,因此ORC文件占用的存储空间也更小。
  5. 在新版本的ORC中也加入了对Bloom Filter的支持,它可以进一 步提升谓词下推的效率,在Hive 1.2.0版本以后也加入了对此的支持。

4.内部表和外部表的区别

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

区别

  1. 内部表数据由Hive自身管理,外部表数据由HDFS管理;
  2. 内部表数据存储的位置是hive.metastore.warehouse.dir(默认:/user/hive/warehouse),外部表数据的存储位置由自己制定(如果没有LOCATION,Hive将在HDFS上的/user/hive/warehouse文件夹下以外部表的表名创建一个文件夹,并将属于这个表的数据存放在这里);
  3. 删除内部表会直接删除元数据(metadata)及存储数据;删除外部表仅仅会删除元数据,HDFS上的文件并不会被删除
  4. 对内部表的修改会将修改直接同步给元数据,而对外部表的表结构和分区进行修改,则需要修复

(MSCK REPAIR TABLE table_name;)。

为什么内部表的删除,就会将数据全部删除,而外部表只删除表结构? 为什么用外部表更好?

问过的一些公司:大华参考答案:

外部表和内部表创建表以及删除时的区别

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

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

外部表的优点
  1. 外部表不会加载数据到Hive的默认仓库(挂载数据),减少了数据的传输,同时还能和其他外部表 共享数据。
  2. 使用外部表,Hive不会修改源数据,不用担心数据损坏或丢失。
  3. Hive在删除外部表时,删除的只是表结构,而不会删除数据。

5.分区表和分桶表

5.1 分区表

分区表实际上就是对应一个 HDFS 文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive 中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。通过WHERE子句查询指定分区,提高查询效率。

5.2 分桶表

create table stu_buck(id int, name string)
clustered by(id) 
into 4 buckets
row format delimited fields terminated by '\t';

分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理的分区。对于一张表或者分区,Hive 可以进一步组织成桶,也就是更为细粒度的数据范围划分。 分桶是将数据集分解成更容易管理的若干部分的另一个技术。

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

6.Hive索引

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

索引适用的场景:

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值