Hive是一个基于Hadoop的开源数仓工具,主要应用于离线的数据场景,在实际工作中使用较多,因此面试时基本会被问到。结合个人面试经历,将常见的面试问题进行总结。
限于篇幅,考虑将面试问题分为上篇及下篇,上篇主要对Hive基本问题进行总结分享。
Hive架构包括如下组件:Metastore、Client、Thrift Server和Driver。
(1)Metastore
元数据,包括表名、表所属的数据库、表的拥有者、列/分区字段、表的类型、表的数据所在目录等内容;
(2)Client
用户接口,主要包含CLI(command language interface)、JDBC或ODBC、WEBUI(以浏览器访问hive);
(3)Thrift Server
提供JDBC/ODBC接入的能力,它用来进行可扩展且跨语言的服务的开发,hive集成了该服务,能让不同的编程语言调用hive的接口;
(4)Driver:(实现将HQL转化为MR过程)
核心组件,整个Hive的核心,它的作用是将我们写的HQL语句进行解析、编译、优化,生成执行计划,然后调用底层的MapReduce计算框架;
(a)解析器(SQL Parser):将SQL字符串转换成抽象语法树AST,这一步一般都用第三方工具库完成,比如antlr;对AST进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误。
(b)优化器(Query Optimizer):对逻辑执行计划进行优化。
(c)编译器(Physical Plan):将AST编译生成逻辑执行计划。
(d)执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。对于Hive来说,就是MR/Spark。
Hive 中所有的数据都存储在 HDFS 中,Hive 中包含以下数据模型:Table,External Table,Partition,Bucket。
2.2.1 表定义
Hive有内部表、外部表、分区表、分桶表4种类型以满足不同的业务场景,简化使用方式,提高生产速度。
1)内部表,就是一般的表,前面讲到的表都是内部表,当表定义被删除的时候,表中的数据随之一并被删除。
2) 外部表,数据存在与否和表的定义互不约束,仅仅只是表对hdfs上相应文件的一个引用,当删除表定义的时候,表中的数据依然存在。
3) 分区表:只需要在之前的创建表后面使用partition by加上分区字段就可以了
4) 分桶表:桶表是对数据进行哈希取值,然后放到不同文件中存储。查看每个桶文件中的内容,可以看出是通过对 buckets 取模确定的。
2.2.2 表区别
1)内部表与外部表的区别
删除数据时,内部表删除原始数据;外部表只删除元数据,没有删除原始数据;
内部表在创建临时表时使用,一般个人使用;外部表使用较多,一般大家都使用;
2)分桶与分区的区别
分桶和分区最大的区别就是分桶随机分割数据库,分区是非随机分割数据库。因为分桶是按照列的哈希函数进行分割的,相对比较平均;而分区是按照列的值来进行分割的,容易造成数据倾斜。
另一个区别就是分桶是对应不同的文件(细粒度),分区是对应不同的文件夹(粗粒度)。
分桶是垂直划分,桶是通过对指定列进行哈希计算来实现的,通过哈希值将一个列名下的数据切分为一组桶,并使每个桶对应于该列名下的一个存储文件,hive使用对分桶所用的值进行hash,并用hash结果除以桶的个数做取余运算的方式来分桶,保证了每个桶中都有数据,但每个桶中的数据条数不一定相等。
分区是表的部分列的集合,可以为频繁使用的数据建立分区,这样查找分区中的数据时就不需要扫描全表,这对于提高查找效率很有帮助,水平划分。
分桶是存储在文件中,分区是存放在文件夹中,分桶要比分区查询效率高。
1)普通创建
create table student2(
num int,
name string)
row format delimited fields terminated by'\t';
2)子查询方式(抽取源表的部分字段分析数据)
create table student_child as select * from student;
3)like方式只是将表结构完全复制一份,不包含数据
create table student_like like student;
4)通过show create table student_child可以得到自动生成的建表语句, 可以通过得到的信息在不同的集群中直接创建相应的表。
hive (hadoop)> show create table student_child;
OK
createtab_stmt
CREATE TABLE `student_child`(
`num` int,
`name` string)
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
'hdfs://172.19.199.187:8020/user/hive/warehouse/hadoop.db/student_child'
TBLPROPERTIES (
'COLUMN_STATS_ACCURATE'='true',
'numFiles'='1',
'numRows'='18',
'rawDataSize'='102',
'totalSize'='120',
'transient_lastDdlTime'='1541461438')
Time taken: 1.014 seconds, Fetched: 18 row(s)
1)Order By:全局排序,只有一个Reducer;Total Job=1,可以在运行日志中看到number of reucers=1.用在select语句的后面。
2)Distrbute By:分区排序, 类似MR中Partition,进行分区,结合sort by使用;
3)Sort By:分区内有序;每个reducer内部进行排序,对全局结果集来说不是排序。随机分区,防止数据倾斜。①设置reduce个数。set mapreduce.job.reducers=3;②查看reduce个数。set mapreduce.job.reducers;
4)Cluster By:当Distribute by和Sorts by字段相同时,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外还兼具Sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC
1) rank函数返回一个唯一的值,除非遇到相同的数据时,此时所有相同数据的排名是一样的,同时会在最后一条相同记录和下一条不同记录的排名之间空出排名。
1,2,2,4....
2) dense_rank函数返回一个唯一的值,除非当碰到相同数据时,此时所有相同数据的排名都是一样的, 没有空出排名。
1,2,2,2,3,3,,4,5
3) row_number函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。
1,2,3,4,5,6
以下结合个人使用情况举例,属于自由发挥类型面试题,回答出两到三个高频使用内置函数即可。
1)行转列
CONCAT(string A/col, string B/col…):
返回输入字符串连接后的结果,支持任意个输入字符串;
CONCAT_WS(separator, str1, str2,…):
它是一个特殊形式的 CONCAT()。第一个参数剩余参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;
COLLECT_SET(col):
函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段。
2)列转行
EXPLODE(col):
将hive一列中复杂的array或者map结构拆分成多行。
LATERAL VIEW:
用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。
3)日期处理函数
date_format函数(根据格式整理日期);
date_add函数(加减日期);
date_sub函数(加减日期);
next_day函数(求每周的指标);
last_day函数(求当月最后一天日期);
Hive 中有如下的数据文件格式: textfile , sequencefile, avro, rcfile , orcfile , parquet, 自定义存储格式,一般ORC格式使用较多。
定义及主要区别如下:
1) TEXTFILE :
textfile 为默认的数据存储格式,textfile 以文本文件的形式存储数据,该种方式默认不对数据进行压缩处理,效率比较低下。 一般极少采用这种方式。
2) SEQUENCEFILE :
存储特点:二进制文件,以
存储方式:行存储
特点:可分割,压缩。支持三种压缩选择:NONE,RECORD,BLOCK。Record压缩率低,一般建议使用BLOCK压缩。压缩模式一般选择block压缩, 优势是文件和Hadoop api中的mapfile是相互兼容的。
3) AVRO:
Avro(读音类似于[ævrə])是Hadoop的一个子项目,由Hadoop的创始人Doug Cutting牵头开发。Avro是一个数据序列化系统,设计用于支持大批量数据交换的应用。
它的主要特点有:支持二进制序列化方式,可以便捷,快速地处理大量数据;动态语言友好,Avro提供的机制使动态语言可以方便地处理Avro数据。
4) RCFILE:
Record Columnar的缩写。是Hadoop中第一个列文件格式。能够很好的压缩和快速的查询性能,但是不支持模式演进。通常写操作比较慢,比非列形式的文件格式需要更多的内存空间和计算量。
存储方式:数据按行分块 每块按照列存储。
主要优势:1.压缩快 快速列存取;2.读记录尽量涉及到的block最少。读取需要的列只需要读取每个row group 的头部定义;3. 读取全量数据的操作 性能可能比sequencefile没有明显的优势
5) ORCFILE:
ORC(OptimizedRC File)存储源自于RC(RecordColumnar File)这种存储格式,RC是一种列式存储引擎。对schema演化(修改schema需要重新生成数据)支持较差,而ORC是对RC改进,但它仍对schema演化支持较差。主要是在压缩编码,查询性能方面做了优化。RC/ORC最初是在Hive中得到使用,最后发展势头不错,独立成一个单独的项目。
相对于 RCFILE :
效率比rcfile高,是rcfile的改良版本,相比RC能够更好的压缩,能够更快的查询,但还是不支持模式演进。
Hive 1.x版本对事务和update操作的支持,便是基于ORC实现的(其他存储格式暂不支持)。
ORC发展到今天,已经具备一些非常高级的feature,比如支持update操作,支持ACID,支持struct,array复杂类型。你可以使用复杂类型构建一个类似于parquet的嵌套式数据架构,但当层数非常多时,写起来非常麻烦和复杂,而parquet提供的schema表达方式更容易表示出多级嵌套的数据类型。
6) PARQUET:
Parquet能够很好的压缩,有很好的查询性能,支持有限的模式演进。但是写速度通常比较慢。这中文件格式主要是用在Cloudera Impala上面的。
存储方式: 列存储
7) 自定义存储格式:
用户可以通过实现InputFormat 和 OutputFormat 来自定义输入输出格式。
1) 定义及使用场景
UDF;
用户定义函数(user-defined function),用于对单行记录进行处理,难度相对简单。
UDAF:
用户定义聚集函数(user-defined aggregate function),用于单行记录转换成多行记录,难度中等。
UDTF:
用户定义表生成函数(user-defined table-generating function),用于多行记录汇总成一行,常用于聚合函数,难度最大。
2)说明:
UDF: 返回对应值,一对一;
UDAF:返回聚类值,多对一;
UDTF:返回拆分值,一对多;
一般udf及udtf函数难度不大,重点在于编写udaf函数。关于如何编写udaf函数,可参考前期文章:
如何编写udaf函数?
以上就是对Hive常见面试题(上篇)的回顾,侧重Hive架构、关键字区别及实际使用经验,下篇将重点介绍数据倾斜优化、Hive性能调优、与其他数据技术区别等。
欢迎大家评论交流,希望本文对大家有所帮助!祝大家面试顺利!