1、什么是Hive,为什么要用Hive,你是如何理解Hive?
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能(HQL)。「Hive本质是将SQL转换为MapReduce的任务进行运算。」
个人理解:hive存的是和hdfs的映射关系,hive是逻辑上的数据仓库,实际操作的都是hdfs上的文件,HQL就是用sql语法来写的mr程序。
2、介绍一下Hive架构

· Hive可以通过CLI,JDBC和 ODBC 等客户端进行访问。除此之外,Hive还支持 WUI 访问
· Hive内部执行流程:解析器(解析SQL语句)、编译器(把SQL语句编译成MapReduce程序)、优化器(优化MapReduce程序)、执行器(将MapReduce程序运行的结果提交到HDFS)
· Hive的「元数据」保存在数据库中,如保存在MySQL,SQLServer,PostgreSQL,Oracle及Derby等数据库中。Hive中的元数据信息包含表名,列名,分区及其属性,表的属性(包括是否为外部表),表数据所在目录等。
· Hive将大部分 HiveSQL语句转化为MapReduce作业提交到Hadoop上执行;少数HiveSQL语句不会转化为MapReduce作业,直接从DataNode上获取数据后按照顺序输出。
3、SQL转化为MapReduce的过程,整个编译过程分为六个阶段:

1、Antlr定义SQL的语法规则,完成SQL词法,语法解析,将SQL转化为抽象语法树AST Tree
2、遍历AST Tree,抽象出查询的基本组成单元QueryBlock
3、遍历QueryBlock,翻译为执行操作树OperatorTree
4、逻辑层优化器进行OperatorTree变换,合并不必要的ReduceSinkOperator,减少shuw le数据量
5、遍历OperatorTree,翻译为MapReduce任务
6、物理层优化器进行MapReduce任务的变换,生成最终的执行计划
4、Hive和数据库比较
Hive 和 数据库 实际上并没有可比性,除了拥有类似的查询语言,再无类似之处。
· 数据存储位置
Hive 存储在HDFS,数据库将数据保存在块设备或者本地文件系统中。
· 数据更新
Hive中不建议对数据的改写,而数据库中的数据通常是需要经常进行修改的。
· 执行延迟
Hive 执行延迟较高。数据库的执行延迟较低。当然,这个是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。
· 数据规模
Hive支持很大规模的数据计算;数据库可以支持的数据规模较小。
5、内部表和外部表的区别,以及各自的使用场景
· 内部表
如果Hive中没有特别指定,则默认创建的表都是「管理表」,也称「内部表」。由Hive负责管理表中的数据,管理表不共享数据。删除管理表时,会删除管理表中的数据和元数据信息。
· 外部表
当一份数据需要「被共享」时,可以创建一个「外部表」指向这份数据。
删除该表并不会删除掉原始数据,删除的是表的元数据。当表结构或者分区数发生变化时,需要进行一步修复的操作。
6、4个By区别
· Sort By:分区内有序
· Order By:全局排序,只有一个Reducer
· Distrbute By:类似MR中Partition,进行分区,结合sort by使用
· Cluster By:当Distribute by和Sorts by字段相同时,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外还兼具Sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。
7、系统函数(了解和使用过哪些Hive函数)
1)date_add、date_sub函数(加减日期)
2)next_day函数(返回输入日期开始,紧随其后的指定星期对应的日期)
3)date_format函数(根据格式整理日期)
4)last_day函数(求当月最后一天日期)
5)列转行:
CONCAT:
返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL。
CONCAT_WS:
contcat_ws() 代表 CONCAT With Separator ,是CONCAT()的特殊形式。第一个参数是其它参数的分隔符。分隔符的位置放在要连接的两个字符串之间。分隔符可以是一个字符串,也可以是其它参数。
注意:
如果分隔符为 NULL,则结果为 NULL。函数会忽略任何分隔符参数后的 NULL 值。
COLLECT_SET:它们都是将分组中的某列转为一个数组返回
6)行转列
EXPLODE
用法:lateral view udtf(expression) tableAlias AS columnAlias
- lateral view:横向视图,用于从UDTF生成的表中选择数据。
- udtf(expression):定义UDTF,并使用表达式作为参数传递。
- tableAlias:表示UDTF生成的表的别名。
- columnAlias:表示UDTF生成的表中的列别名。
7)get_json_object解析json函数
8)NVL(表达式1,表达式2)
如果表达式1为空值,NVL返回值为表达式2的值,否则返回表达式1的值。
8、Hive窗口函数的区别
· RANK() 排序相同时会重复,总数不会变,例如1224
· DENSE_RANK() 排序相同时会重复,总数会减少,例如 1223
· ROW_NUMBER() 会根据顺序去计算,例如 1234
9、自定义UDF、UDTF函数
在项目中是否自定义过UDF、UDTF函数,以及用他们处理了什么问题,及自定义步骤?
你可以这么回答:
<1> 自定义过
<2> 我一般用UDF函数解析公共字段;用UDTF函数解析事件字段
具体的步骤对应如下:
「自定义UDF」:继承UDF,重写evaluate方法
「自定义UDTF」:继承自GenericUDTF,重写3个方法:initialize(自定义输出的列名和类型),process(将结果返回forward(result)),close
为什么要自定义UDF/UDTF?
因为自定义函数,可以自己埋点Log打印日志,出错或者数据异常,方便调试
10、Hive优化
当被问到优化,你应该庆幸自己这趟面试来得值了。为啥?下面的这九大步,面试官还不得当场呆住,这波稳了的节奏~

· MapJoin
如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。
· 行列过滤
列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT *。
行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤。
· 合理设置Map数
是不是map数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是「受限」的。此时我们就应该减少map数量。
· 合理设置Reduce数
Reduce个数并不是越多越好
(1)过多的启动和初始化Reduce也会消耗时间和资源;
(2)另外,有多少个Reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置Reduce个数的时候也需要考虑这两个「原则」:处理大数据量利用合适的Reduce数;使单个Reduce任务处理数据量大小要合适;
· 严格模式
严格模式下,会有以下特点:
①对于分区表,用户不允许扫描所有分区
②使用了order by语句的查询,要求必须使用limit语句
③限制笛卡尔积的查询
· 开启map端combiner(不影响最终业务逻辑)
这个就属于配置层面上的优化了,需要我们手动开启 sethive.map.aggr=true;
· 压缩(选择快的)
设置map端输出中间结果压缩。(不完全是解决数据倾斜的问题,但是减少了IO读写和网络传输,能提高很多效率)
· 小文件进行合并
在Map执行前合并小文件,减少Map数:CombineHiveInputFormat具有对小文件进行合并的功能(系统默认的格式)。HiveInputFormat没有对小文件合并功能。
· 其他
列式存储,采用分区技术,开启JVM重用...类似的技术非常多,大家选择一些方便记忆的就OK。
11、了解过数据倾斜吗,是如何产生的,你又是怎么解决的?

· 概念:
数据的分布不平衡,某些地方特别多,某些地方又特别少,导致的在处理数据的时候,有些很快就处理完了,而有些又迟迟未能处理完,导致整体任务最终迟迟无法完成,这种现象就是「数据倾斜」
· 如何产生
① key的分布不均匀或者说某些key太集中
② 业务数据自身的特性,例如不同数据类型关联产生数据倾斜
③ SQL语句导致的数据倾斜
· 如何解决
① 开启map端combiner(不影响最终业务逻辑)
② 开启数据倾斜时负载均衡
③ 控制空值分布
“将为空的key转变为字符串加随机数或纯随机数,将因空值而造成倾斜的数据分配到多个Reducer”
④ SQL语句调整
“
a ) 选用join key 分布最均匀的表作为驱动表。做好列裁剪和filter操作,以达到两表join的时候,数据量相对变小的效果。
b ) 大小表Join:使用map join让小的维度表(1000条以下的记录条数)先进内存。在Map端完成Join。
c ) 大表Join大表:A表加随机数 B表扩容 后再Join
d ) count distinct大量相同特殊值:count distinct 时,将值为空的情况单独处理,如果是计算count distinct,可以不用处理,直接过滤,在最后结果中加1。如果还有其他计算,需要进行group by,可以先将值为空的记录单独处理,再和其他计算结果进行union。
”
12、分区表和分桶表各自的优点能介绍一下吗?
· 分区表
· 介绍
1、分区使用的是表外字段,需要指定字段类型
2、分区通过关键字 partitioned by(partition_name string) 声明
3、分区划分粒度较粗
· 优点
将数据按区域划分开,查询时不用扫描无关的数据,加快查询速度
· 分桶表
· 介绍
1、分桶使用的是表内字段,已经知道字段类型,不需要再指定。
2、分桶表通过关键字clustered by(column_name) into ... buckets声明
3、分桶是更细粒度的划分、管理数据,可以对表进行先分区再分桶的划分策略
· 优点
用于数据取样;能够起到优化加速的作用
回答到这里已经非常不错,面试官可能又问了:
「小伙几,能讲解一下分桶的逻辑吗?」
哈哈哈,有备而来,丝毫不惧!!!
“
分桶逻辑:对分桶字段求哈希值,用哈希值与分桶的数量取余,余几,这个数据就放在那个桶内。
”
13、用的是动态分区吗?动态分区的底层原理是什么?
都到了这一步,没有撤退可言。
· 静态分区与动态分区的主要区别在于静态分区是手动指定,而动态分区是通过数据来进行判断
· 详细来说,静态分区的列是在编译时期,通过用户传递来决定的;动态分区只有在 SQL 执行时才能决定
· 简单理解就是静态分区是只给固定的值,动态分区是基于查询参数的位置去推断分区的名称,从而建立分区
14、使用过Hive的视图和索引吗,简单介绍一下
· Hive视图
视图是一种使用查询语句定义的「虚拟表」,是数据的一种「逻辑结构」,创建视图时不会把视图存储到磁盘上,定义视图的查询语句只有在执行视图的语句时才会被执行。
通过引入视图机制,可以简化查询逻辑,提高了用户效率与用户满意度。
「注意:」视图是只读的,不能向视图中插入或是加载数据
· Hive索引
和关系型数据库中的索引一样,Hive也支持在表中建立索引。适当的索引可以优化Hive查询数据的性能。但是索引需要额外的存储空间,因此在创建索引时需要考虑索引的必要性。
「注意:」Hive不支持直接使用DROP TABLE语句删除索引表。如果创建索引的表被删除了,则其对应的索引和索引表也会被删除;如果表的某个分区被删除了,则该分区对应的分区索引也会被删除。