hive
- 1. Hive内部表和外部表的区别
- 2. Hive有索引吗
- 3. 运维如何对Hive进行调度
- 4. ORC、Parquet等列式存储的优点
- 5. 数据建模用的哪些模型?
- 6. 为什么要对数据仓库分层?
- 7. 使用过Hive解析JSON串吗
- 8. sort by 和 order by 的区别
- 9. 数据倾斜怎么解决
- 10. Hive 小文件过多怎么解决
- 11. 小文件过多产生的影响
- 12. Hive优化有哪些
- 13. Tez引擎优点?
- 14. hive基于MapReduce过程详解及其性能优化
- 15.hive 什么是分区表以及静态分区和动态分区的区别
- 16. Hive 的两张表关联,使用 MapReduce怎么实现?
- 17. Hive 中的压缩格式 TextFile、SequenceFile、RCfile、ORCfile各有什么区别?
- 18.Hive 的函数:UDF、UDAF、UDTF 的区别?
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索引提供的功能很有限,效率也并不高,因此Hive索引很少使用。
-
索引适用的场景:
适用于不更新的静态字段。以免总是重建索引数据。每次建立、更新数据后,都要重建索引以构建索引表。 -
Hive索引的机制如下:
hive在指定列上建立索引,会产生一张索引表(Hive的一张物理表),里面的字段包括:索引列的值、该值对应的HDFS文件路径、该值在文件中的偏移量。
Hive 0.8版本后引入bitmap索引处理器,这个处理器适用于去重后,值较少的列(例如,某字段的取值只可能是几个枚举值) 因为索引是用空间换时间,索引列的取值过多会导致建立bitmap索引表过大。
注意:Hive中每次有数据时需要及时更新索引,相当于重建一个新表,否则会影响数据查询的效率和准确性,Hive官方文档已经明确表示Hive的索引不推荐被使用,在新版本的Hive中已经被废弃了。
扩展:Hive是在0.7版本之后支持索引的,在0.8版本后引入bitmap索引处理器,在3.0版本开始移除索引的功能,取而代之的是2.3版本开始的物化视图,自动重写的物化视图替代了索引的功能。
3. 运维如何对Hive进行调度
-
将hive的sql定义在脚本当中;
-
使用azkaban或者oozie进行任务的调度;
-
监控任务调度页面。
4. ORC、Parquet等列式存储的优点
ORC和Parquet都是高性能的存储方式,这两种存储格式总会带来存储和性能上的提升。
Parquet:
- Parquet支持嵌套的数据模型,类似于Protocol Buffers,每一个数据模型的schema包含多个字段,每一个字段有三个属性:重复次数、数据类型和字段名。
重复次数可以是以下三种:required(只出现1次),repeated(出现0次或多次),optional(出现0次或1次)。每一个字段的数据类型可以分成两种: group(复杂类型)和primitive(基本类型)。- Parquet中没有Map、Array这样的复杂数据结构,但是可以通过repeated和group组合来实现的。
- 由于Parquet支持的数据模型比较松散,可能一条记录中存在比较深的嵌套关系,如果为每一条记录都维护一个类似的树状结可能会占用较大的存储空间,因此Dremel论文中提出了一种高效的对于嵌套数据格式的压缩算法:Striping/Assembly算法。通过Striping/Assembly算法,parquet可以使用较少的存储空间表示复杂的嵌套格式,并且通常Repetition level和Definition level都是较小的整数值,可以通过RLE算法对其进行压缩,进一步降低存储空间。
Parquet文件是以二进制方式存储的,是不可以直接读取和修改的,Parquet文件是自解析的,文件中包括该文件的数据和元数据。
ORC:
- ORC文件是自描述的,它的元数据使用Protocol Buffers序列化,并且文件中的数据尽可能的压缩以降低存储空间的消耗。
- 和Parquet类似,ORC文件也是以二进制方式存储的,所以是不可以直接读取,ORC文件也是自解析的,它包含许多的元数据,这些元数据都是同构ProtoBuffer进行序列化的。
- ORC会尽可能合并多个离散的区间尽可能的减少I/O次数。
- ORC中使用了更加精确的索引信息,使得在读取数据时可以指定从任意一行开始读取,更细粒度的统计信息使得读取ORC文件跳过整个row group,ORC默认会对任何一块数据和索引信息使用ZLIB压缩,因此ORC文件占用的存储空间也更小。
- 在新版本的ORC中也加入了对Bloom Filter的支持,它可以进一 步提升谓词下推的效率,在Hive 1.2.0版本以后也加入了对此的支持。
5. 数据建模用的哪些模型?
1. 星型模型
星形模式(Star Schema)是最常用的维度建模方式。星型模式是以事实表为中心,所有的维度表直接连接在事实表上,像星星一样。 星形模式的维度建模由一个事实表和一组维表成,且具有以下特点:
a. 维表只和事实表关联,维表之间没有关联;
b. 每个维表主键为单列,且该主键放置在事实表中,作为两边连接的外键;
c. 以事实表为核心,维表围绕核心呈星形分布。
2. 雪花模型
雪花模式(Snowflake Schema)是对星形模式的扩展。雪花模式的维度表可以拥有其他维度表的,虽然这种模型相比星型更规范一些,但是由于这种模型不太容易理解,维护成本比较高,而且性能方面需要关联多层维表,性能比星型模型要低。
3. 星座模型
星座模式是星型模式延伸而来,星型模式是基于一张事实表的,而星座模式是基于多张事实表的,而且共享维度信息。前面介绍的两种维度建模方法都是多维表对应单事实表,但在很多时候维度空间内的事实表不止一个,而一个维表也可能被多个事实表用到。在业务发展后期,绝大部分维度建模都采用的是星座模式。
数仓建模详细介绍可查看:通俗易懂数仓建模: 数仓建模
6. 为什么要对数据仓库分层?
用空间换时间,通过大量的预处理来提升应用系统的用户体验(效率),因此数据仓库会存在大量冗余的数据。
如果不分层的话,如果源业务系统的业务规则发生变化将会影响整个数据清洗过程,工作量巨大。
通过数据分层管理可以简化数据清洗的过程,因为把原来一步的工作分到了多个步骤去完成,相当于把一个复杂的工作拆成了多个简单的工作,把一个大的黑盒变成了一个白盒,每一层的处理逻辑都相对简单和容易理解,这样我们比较容易保证每一个步骤的正确性,当数据发生错误的时候,往往我们只需要局部调整某个步骤即可。
数据仓库详细介绍可查看:万字详解整个 数据仓库建设体系
7. 使用过Hive解析JSON串吗
Hive处理json数据总体来说有两个方向的路走:
-
将json以字符串的方式整个入Hive表,然后通过使用UDF函数解析已经导入到hive中的数据,比如使用get_json_object的方法,获取所需要的列名。
-
在导入之前将json拆成各个字段,导入Hive表的数据是已经解析过的。这将需要使用第三方的 JSONSerDe。
详细介绍可查看:Hive解析Json数组超全讲解
8. sort by 和 order by 的区别
order by 会对输入做全局排序,因此只有一个reducer(多个reducer无法保证全局有序)只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。
sort by不是全局排序,其在数据进入reducer前完成排序. 因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1, 则sort by只保证每个reducer的输出有序,不保证全局有序。
9. 数据倾斜怎么解决
定义:在Hive中,数据倾斜是指在数据处理过程中某些任务或分区的数据量远远超过其他任务或分区,导致计算资源不平衡和性能下降的情况。下面是一些常见的方法来解决Hive中的数据倾斜问题:
- 空值引发的数据倾斜
- 不同数据类型引发的数据倾斜
- 不可拆分大文件引发的数据倾斜
- 数据膨胀引发的数据倾斜
- 表连接时引发的数据倾斜
- 确实无法减少数据量引发的数据倾斜
以上倾斜问题的具体解决方案可查看:Hive千亿级数据倾斜解决方案
注意:对于 left join 或者 right join 来说,不会对关联的字段自动去除null值,对于 inner join 来说,会对关联的字段自动去除null值。
解决办法
- 预分区(Pre-partitioning):在数据加载到Hive表之前,可以通过合理的预分区策略将数据划分为更细粒度的分区。这样可以将数据均匀分布到不同的分区中,减少数据倾斜的可能性。
- 增加分区数或Reduce任务数:如果数据倾斜发生在某些特定分区或Reduce任务上,可以考虑增加分区数或Reduce任务数。这样可以将负载均衡到更多的分区或任务中,减少数据倾斜的影响。
- 采用随机前缀(Randomized Prefix):对于导致数据倾斜的关键字段,可以在查询过程中引入随机前缀来打破数据的集中倾斜。例如,在JOIN操作中,可以对连接键的值进行哈希运算,然后添加一个随机前缀,使数据更加均匀地分布到不同的任务中。
- 聚合重分发(Aggregation Redistribution):如果数据倾斜发生在某个聚合操作中,可以考虑在聚合之前进行数据重分发。可以通过先对部分数据进行聚合,然后再将结果进行全局聚合,从而减少单个任务的负载。
- 使用Combiner或Partial Aggregation:对于某些操作,可以通过使用Combiner或Partial Aggregation来减少数据传输量。这样可以减少数据倾斜对网络带宽和计算资源的影响。
- 动态调整资源:根据任务运行时的情况,可以动态调整资源分配。例如,可以根据任务进度、数据量等因素调整MapReduce任务的资源配置,以使负载更加均衡。
- 数据重分布(Data Redistribution):如果数据倾斜问题比较严重且无法通过其他方法解决,可以考虑对数据进行重分布。可以将倾斜的数据提取出来,重新进行分区或重新设计数据模型,以实现更均匀的数据分布。
以上是一些常见的方法来解决Hive中的数据倾斜问题。具体选择哪种方法取决于数据倾斜的具体情况和业务需求。在实际应用中,可能需要尝试多种方法的组合,并根据实际情况进行调整和优化。
10. Hive 小文件过多怎么解决
- 使用 hive 自带的 concatenate 命令,自动合并小文件
#对于非分区表
alter table A concatenate;
#对于分区表
alter table B partition(day=20201224) concatenate;
注意:
1、concatenate 命令只支持 RCFILE 和 ORC 文件类型。
2、使用concatenate命令合并小文件时不能指定合并后的文件数量,但可以多次执行该命令。
3、当多次使用concatenate后文件数量不在变化,这个跟参数 mapreduce.input.fileinputformat.split.minsize=256mb 的设置有关,可设定每个文件的最小size。
- 调整参数减少Map数量
设置map输入合并小文件的相关参数(执行Map前进行小文件合并):
在mapper中将多个文件合成一个split作为输入(CombineHiveInputFormat底层是Hadoop的CombineFileInputFormat方法):
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; -- 默认
3. 减少Reduce的数量
reduce 的个数决定了输出的文件的个数,所以可以调整reduce的个数控制hive表的文件数量。
hive中的分区函数 distribute by 正好是控制MR中partition分区的,可以通过设置reduce的数量,结合分区函数让数据均衡的进入每个reduce即可:
#设置reduce的数量有两种方式,第一种是直接设置reduce个数
set mapreduce.job.reduces=10;
#第二种是设置每个reduce的大小,Hive会根据数据总大小猜测确定一个reduce个数
set hive.exec.reducers.bytes.per.reducer=5120000000; -- 默认是1G,设置为5G
#执行以下语句,将数据均衡的分配到reduce中
set mapreduce.job.reduces=10;
insert overwrite table A partition(dt)
select * from B
distribute by rand();
对于上述语句解释:如设置reduce数量为10,使用 rand(), 随机生成一个数 x % 10 , 这样数据就会随机进入 reduce 中,防止出现有的文件过大或过小。
4. 使用hadoop的archive将小文件归档
Hadoop Archive简称HAR,是一个高效地将小文件放入HDFS块中的文件存档工具,它能够将多个小文件打包成一个HAR文件,这样在减少namenode内存使用的同时,仍然允许对文件进行透明的访问。
#用来控制归档是否可用
set hive.archive.enabled=true;
#通知Hive在创建归档时是否可以设置父目录
set hive.archive.har.parentdir.settable=true;
#控制需要归档文件的大小
set har.partfile.size=1099511627776;
使用以下命令进行归档:
ALTER TABLE A ARCHIVE PARTITION(dt='2021-05-07', hr='12');
对已归档的分区恢复为原文件:
ALTER TABLE A UNARCHIVE PARTITION(dt='2021-05-07', hr='12');
注意:
归档的分区可以查看不能 insert overwrite,必须先 unarchive
Hive 小文件问题具体可查看:解决hive小文件过多问题
11. 小文件过多产生的影响
- 首先对底层存储HDFS来说,HDFS本身就不适合存储大量小文件,小文件过多会导致namenode元数据特别大, 占用太多内存,严重影响HDFS的性能
- 对 hive 来说,在进行查询时,每个小文件都会当成一个块,启动一个Map任务来完成,而一个Map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的Map数量是受限的。
12. Hive优化有哪些
- 数据存储及压缩:
- 针对hive中表的存储格式通常有orc和parquet,压缩格式一般使用snappy。相比与textfile格式表,orc占有更少的存储。因为hive底层使用MR计算架构,数据流是hdfs到磁盘再到hdfs,而且会有很多次,所以使用orc数据格式和snappy压缩策略可以降低IO读写,还能降低网络传输量,这样在一定程度上可以节省存储,还能提升hql任务执行效率;
- 通过调参优化:
并行执行,调节parallel参数;
调节jvm参数,重用jvm;
设置map、reduce的参数;开启strict mode模式;
关闭推测执行设置。
- 有效地减小数据集将大表拆分成子表;结合使用外部表和分区表。
- SQL优化
- 大表对大表:尽量减少数据集,可以通过分区表,避免扫描全表或者全字段;
- 大表对小表:设置自动识别小表,将小表放入内存中去执行。
Hive优化详细剖析可查看:Hive企业级性能优化
13. Tez引擎优点?
Tez可以将多个有依赖的作业转换为一个作业,这样只需写一次HDFS,且中间节点较少,从而大大提升作业的计算性能。
Mr/tez/spark区别:
Mr引擎:多job串联,基于磁盘,落盘的地方比较多。虽然慢,但一定能跑出结果。一般处理,周、月、年指标。
Spark引擎:虽然在Shuffle过程中也落盘,但是并不是所有算子都需要Shuffle,尤其是多算子过程,中间过程不落盘 DAG有向无环图。 兼顾了可靠性和效率。一般处理天指标。
Tez引擎:完全基于内存。 注意:如果数据量特别大,慎重使用。容易OOM。一般用于快速出结果,数据量比较小的场景。
14. hive基于MapReduce过程详解及其性能优化
15.hive 什么是分区表以及静态分区和动态分区的区别
15.1 什么是分区表
分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。在查询时通过WHERE子句中的表达式选择查询所需要的指定的分区,分区目的主要是避免全表扫描,从而提升查询和计算效率。
按分区类型划分,可以分为静态分区、动态分区。
1、静态分区
静态分区是指增加数据是需要手动指定具体的分区目录
静态分区的列实在编译时期,通过用户传递列名来决定的
静态分区不管有没有数据都将会创建该分区
2、动态分区
动态分区增加数据时不用手动指定分区目录,而是由系统通过数据来进行判断。
动态分区实在SQL执行的时候确定的。
动态分区是有结果集将创建分区,否则不创建。
动态分区虽然方便快捷,但创建太多分区时可能会占用大量资源。
15.2 分区表与分桶表的区别?
1)
分区表:使用的是表外字段(表中不存在的字段),需要指定字段类型;
分桶表:使用的是表内字段(表中存在的字段),已经知道字段类型,不需要指定。
2)
分区表:通过关键字partitioned by(partition_name string)声明,
分桶表:通过关键字clustered by(column_name) into 3 buckets声明。
3)
分区表:划分的是hdfs的存储路径(文件夹),是个伪列,只对应着文件存储路径上的一个层级
分桶表:划分的是hdfs的数据文件
16. Hive 的两张表关联,使用 MapReduce怎么实现?
- 如果其中有一张表为小表,直接使用 map 端 join 的方式(map 端加载小表)进行聚合。
- 如果两张都是大表,那么采用联合 key,联合 key 的第一个组成部分是 join on 中的公共字段,第二部分是一个 flag,0 代表表 A,1 代表表 B,由此让Reduce 区分客户信息和订单信息;在 Mapper 中同时处理两张表的信息,将join on 公共字段相同的数据划分到同一个分区中,进而传递到一个 Reduce中,然后在 Reduce 中实现聚合。
17. Hive 中的压缩格式 TextFile、SequenceFile、RCfile、ORCfile各有什么区别?
-
TextFile: 默认格式,数据不做压缩,磁盘开销大,数据解析开销大。可结合Gzip、Bzip2使用,但使用Gzip这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作。
-
SequenceFile: SequenceFile是Hadoop API 提供的一种二进制文件,它将数据以<key,value>的形式序列化到文件中。这种二进制文件内部使用Hadoop 的标准的Writable 接口实现序列化和反序列化。它与Hadoop API中的MapFile 是互相兼容的。Hive 中的SequenceFile 继承自Hadoop API 的SequenceFile,不过它的key为空,使用value 存放实际的值, 这样是为了避免MR 在运行map 阶段的排序过程。
-
RCFile: RCFile是Hive推出的一种专门面向列的数据格式。 它遵循“先按列划分,再垂直划分”的设计理念。当查询过程中,针对它并不关心的列时,它会在IO上跳过这些列。需要说明的是,RCFile在map阶段从 远端拷贝仍然是拷贝整个数据块,并且拷贝到本地目录后RCFile并不是真正直接跳过不需要的列,并跳到需要读取的列, 而是通过扫描每一个row group的头部定义来实现的,但是在整个HDFS Block 级别的头部并没有定义每个列从哪个row group起始到哪个row group结束。所以在读取所有列的情况下,RCFile的性能反而没有SequenceFile高。
-
ORCfile: ORC是列式存储,有多种文件压缩方式,并且有着很高的压缩比。文件是可切分(Split)的。因此,在Hive中使用ORC作为表的文件存储格式,不仅节省HDFS存储资源,查询任务的输入数据量减少,使用的MapTask也就减少了。提供了多种索引,row group index、bloom filter index。ORC可以支持复杂的数据结构(比如Map等)
18.Hive 的函数:UDF、UDAF、UDTF 的区别?
为什么需要 udf
udf,(User Defined Function)用户自定义函数
Hive 的 类 sql 给 开发者和分析者带来了极大的便利,使用 sql 就可以完成海量数据的处理,但是有时候,hive 自带的一些函数可能无法满足需求,这个时候,就需要我们自己定义一些函数,像插件一样在MapReduce过程中生效。
Hive中有3种UDF:
1、用户定义函数(user-defined function)UDF;
2、用户定义聚集函数(user-defined aggregate function,UDAF);
3、用户定义表生成函数(user-defined table-generating function,UDTF)。
UDF:操作单个数据行,产生单个数据行;
UDAF:操作多个数据行,产生一个数据行。
UDTF:操作一个数据行,产生多个数据行一个表作为输出。
简单来说:
UDF:返回对应值,一对一
UDAF:返回聚类值,多对一
UDTF:返回拆分值,一对多