1. 简述 Hive 工作原理​


Hive 的工作原理围绕数据的存储、查询处理和计算执行展开。​
数据存储:Hive 将结构化数据映射到 HDFS 上存储,用户通过定义表结构(包括字段名、数据类型等),将实际存储在 HDFS 的数据文件与表关联起来。数据以文件形式存储,支持多种文件格式,不同格式在存储和查询性能上各有特点。​
查询处理:当用户通过 Hive 命令行、Web UI 等接口提交 HiveQL 查询语句后,Hive 首先将语句发送给查询编译器。编译器对查询语句进行词法分析、语法分析、语义分析,检查语句的合法性,并生成抽象语法树 。接着,通过查询优化器对抽象语法树进行优化,比如重写查询语句、选择更优的执行计划,将 HiveQL 转换为可执行的任务计划,这个计划可以是 MapReduce、Tez 或 Spark 任务。​
计算执行:生成的任务计划被提交到相应的计算引擎执行。以 MapReduce 为例,任务被分解为 Map 阶段和 Reduce 阶段,在 Map 阶段对数据进行初步处理,Reduce 阶段对 Map 输出结果进行聚合等操作 。计算过程中,Hive 通过 MetaStore 访问存储在关系型数据库(如 MySQL)中的元数据,获取表结构、数据位置等信息,保障数据处理的准确性 。最终,计算结果返回给用户接口展示给用户。


 2. Hive 内部表和外部表区别


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


提示:内部表与外部表的区别一定要掌握,通常情况下我们都会使用外部表保证数据安全性,但是像中间表,结果表这种我们就会考虑使用内部表(管理表)


3. 分区和分桶的区别


3.1 分区


是指按照数据表的某列或某些列分为多个区,区从形式上可以理解为文件夹,比如我们要收集某个大型网站的日志数据,一个网站每天的日志数据存在同一张表上,由于每天会生成大量的日志,导致数据表的内容巨大,在查询时进行全表扫描耗费的资源非常多。
那其实这个情况下,我们可以按照日期对数据表进行分区,不同日期的数据存放在不同的分区,在查询时只要指定分区字段的值就可以直接从该分区查找。如果在建表时使用了 PARTITIONED BY,表即为分区表。分区表下的数据按分区键的值(或值的范围)放在HDFS下的不同目录中,可以有效减少查询时扫描的数据量,提升查询效率。


3.2 分桶


分桶是相对分区进行更细粒度的划分。
分桶将整个数据内容安装某列属性值得hash值进行区分,如要按照name属性分为3个桶,就是对name属性值的hash值对3取摸,按照取模结果对数据分桶。
如取模结果为0的数据记录存放到一个文件,取模为1的数据存放到一个文件,取模为2的数据存放到一个文件,如果在建表时使用了 CLUSTERED BY … INTO … BUCKETS,表即为分桶表。分桶表下的数据按分桶键的哈希值放在HDFS下的不同目录中,可以有效减少查询时扫描的数据量,提升查询效率。
总结:分区就是在hdfs上分目录(文件夹),分桶就是分文件。


4. 将数据直接上传到分区目录(hdfs)上,让分区表和数据产生关联有哪些方式?


方案一:上传数据后修复表
dfs -mkdir -p 分区目录
dfs -put 分区目录
msck repair table 表名
方案二:上传数据后添加分区
dfs -mkdir -p 分区目录
dfs -put 分区目录
alter table 表名 add partition();
提示:这里我们如果直接将新的分区文件上传到hdfs上,因为hive没有对应的元数据所以是无法查询到数据的,所以我们要进行表修复或者添加分区。


5. 桶表是否可以通过直接load将数据导入?


不可以,因为load数据的话hdfs下只会有一个文件无法完成分桶的效果,分桶和mapredue中的分区是一样的道理,所以我们要借助中间表导入数据。

6. order by,sort by,distribute by,cluster by的区别?

order by会对所给的全部数据进行全局排序 ,不管来多少数据,都只启动一个reducer来处理 。

sort by是局部排序 ,sort by会根据数据量的大小启动一到多个reducer来干活,并且,它会在进入reduce之前为每个reducer都产生一个排序文件 。

distribute by 控制map结果的分发,它会将具有相同字段的map输出分发到一个reduce节点上做处理 。

cluster by 可以理解为一个特殊的distribute by和sort by的结合,当distribute by和sort by后面所跟的列名相同时,就等同于直接使用cluster by 跟上该列名。但是被cluster by指定的列最终的排序结果只能是升序,而且无法指定asc和desc。

提示:这个问题面试问的频率很高,大家一定要注意区分以下。

7. 聚合函数是否可以写在order by后面,为什么?

不可以。

原因:执行顺序!!!order by的执行顺序在select之后,所以需使用重新定义的列名进行排序。

提示:理解sql的执行顺序更加有利于大家写sql

(1)from

(2)join

(3)on

(4)where

(5)group by

(6)having

(7)select

(8)order by

(9)limit

8. 导致数据倾斜的原因有哪些,有什么解决的方案

数据倾斜是由于数据分布不均匀,造成数据大量的集中到一点,造成数据热点的现象。

    主要表现:任务进度长时间维持在 99%或者 100%的附近,查看任务监控页面,发现只有少量 reduce 子任务未完成,因为其处理的数据量和其他的 reduce 差异过大。 单一 reduce 处理的记录数和平均记录数相差太大,通常达到好几倍之多,最长时间远大于平均时长。

导致数据倾斜的原因:

1.数据类型不一致导致数据倾斜

解决方法:

进行类型转换

2.数据中出现大量null值

解决方法:分两种情况,第一种情况null是异常值,对于异常值如果不需要的话,最好是提前在where条件里过滤掉,这样可以使计算量大大减少;第二种情况不是异常数据,虽然某个 key 为空对应的数据很多,但是相应的数据不是异常数据,必须要包含在join 的结果中,此时我们可以表 a 中 key 为空的字段赋一个随机的值,使得数据随机均匀地分不到不同的 reducer 上。

3.单表group by:导致数据倾斜的主要原因在于按照 Key 分组以后,少量的任务负责绝大部分数据的计算,也就是说产生数据倾斜的 HQL 中一定存在分组操作,那么从 HQL 的角度,我们可以将数据倾斜分为单表携带了 GroupBy 字段的查询和两表(或者多表)Join 的查询。

解决方法:

第一种方案:使用参数优化

当任务中存在group by操作同时聚合函数为count或者sum,可以设置参数来处理数据倾斜的问题。

第二种方案:增加Reduce数量

当数据中的多个key同时导致数据倾斜,可以通过增加reduce的数量解决数据倾斜问题

4.多表join

解决方法:

解决方案一:使用参数解决

第二种解决方案:大小表join:可以使用MapJoin,没有Reduce阶段就不会出现数据倾斜,还可以使用大表打散小表扩容的手段解决。

9.hive中常见数据压缩格式

压缩方式 压缩比 压缩速度 解压缩速度 是否可分割
gzip 13.4% 21 MB/s 118 MB/s
bzip2 13.2% 2.4MB/s 9.5MB/s
lzo 20.5% 135 MB/s 410 MB/s
snappy 22.2% 172 MB/s 409 MB/s

Hive 常用压缩算法性能对比表

压缩算法 原始文件大小 压缩文件大小 压缩比 压缩速度 解压速度 是否可分割
gzip 8.3GB 1.8GB 21.7% 17.5MB/s 58MB/s
bzip2 8.3GB 1.1GB 13.3% 2.4MB/s 9.5MB/s
LZO 8.3GB 2.9GB 34.9% 49.3MB/s 74.6MB/s
Snappy 8.3GB 2.5GB* 30.1%* 172MB/s* 409MB/s*

 10.hive中常见的文件存储格式

存储格式 查询性能 压缩效率 写入速度 支持列裁剪 支持嵌套结构 跨引擎兼容性
TextFile
SequenceFile
RCFile
ORC
Parquet
Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐