Hive知识点复习整理

Hive面试题整理
一、Hive的架构

(1)用户接口:client

CLI、JDBC/ODBC(jdbc访问hive)、WEBUI(浏览器访问hive)

(2)元数据:Metastore

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

默认存储在自带的derby数据库中,通常使用Mysql存储metastore

(3)Hadoop

使用HDFS进行存储,使用MR进行计算

(4)驱动器Driver

1.解析器:将SQL字符串转换成抽象语法树AST,对AST进行语法分析(检查:表是否存在、字段是否存在、SQL语义是否有误等)

2.编译器:将AST编译生成逻辑执行计划

3.优化器:对执行逻辑进行优化

4.执行器:把逻辑执行计划转换成可以运行的物理计划。对于Hive来说,就是MR/Spark。

二、Hive和数据库进行比较

hive存储在HDFS,数据库存储在块设备或本地文件系统中。

Hive不建议对数据的改写,数据库经常修改。

Hive执行延迟较高,数据库延迟较低。当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。

Hive支持很大规模的数据计算;数据库可以支持的数据规模较小。

三、内部表和外部表

元数据、原始数据

1)删除数据时

内部表:元数据、原始数据,全部删除

外部表:只删除元数据

2)公司绝大多数场景都是外部表;自己使用的临时表,才会创建内部表

四、4个By区别

1)Order By:全局排序,只有一个Reducer;

在生产环境中Order By用的比较少,容易导致OOM(内存耗尽或内存溢出。主要原因是其需要在单个节点上对整个数据集进行全局排序。这种全局排序操作需要将所有数据加载到内存中,并对其进行排序,这可能会导致内存耗尽,特别是当数据量非常大时。)

2)Sort By:分区内有序;

3)Distribute By:类似MR中的Partition,进行分区,结合sort by使用;

4)Cluster By:当distribute by和sorts by字段相同时,可以使用cluster by方式。Cluster by除了具有Distribute by的功能外还兼具Sort by的功能。(但是排序只能是升序排序,不能指定排序规则为ASC或者DESC)

(举个例子,假设有一个大型的销售数据表 sales_data,其中包含了销售订单信息,字段包括 order_id, customer_id, order_date, total_amount 等。我们希望按照 order_date 字段对数据进行分区和排序。

使用 DISTRIBUTE BYSORT BY 可以这样写查询:

SELECT * FROM sales_data
DISTRIBUTE BY order_date
SORT BY order_date;

如果 DISTRIBUTE BYSORT BY 字段相同时,可以使用 CLUSTER BY 来简化查询,并提高执行效率,因为它会同时执行数据的分布和排序:

SELECT * FROM sales_data
CLUSTER BY order_date;

这样,数据将会根据 order_date 字段进行分组,并且每个分组内的数据会按照 order_date 字段排序。这样可以避免在排序过程中进行数据的重复移动,提高了查询的效率。)

生产环境中Sort By+Distribute By用的多。

五、系统函数

1)date_add、date_sub函数(加减日期)

2)next_day函数(周指标相关)

3)date_format函数(根据格式整理日期)

4)last_day函数(求当月最后一天日期)

5)collect_set函数(用于将指定字段的值收集到一个集合中,并去除重复的值)

6)get_json_object解析json

7)NVL(表达式1,表达式2):如果表达式1为空,NVL返回值为表达式2的值,否则返回1的值

六、自定义UDF、UDTF函数

常用UDF函数解析公共字段;用UDTF函数解析事件字段

  1. 公共字段(Attributes):这些字段通常包含与实体或对象相关的静态信息或属性。

    例如,对于一个电子商务网站,公共字段可能包括产品的名称、价格、类别等信息。这些信息通常是固定不变的,不随着时间的推移而改变。

  2. 事件字段(Events):这些字段描述了在特定时间点或时间范围内发生的动态事件或行为。

    例如,对于同一个电子商务网站,事件字段可能包括用户的购买行为、浏览产品的行为、加入购物车的行为等。这些事件通常与特定的时间戳相关联,并且随着时间的推移而产生变化。

自定义UDF函数:继承UDF,重写evaluate方法(实现自己的逻辑处理输入的参数,并返回计算结果)

自定义UDTF函数,继承自GenericUDTF,重写3个方法:initialize(自定义输出的列名和类型),process(将结果返回forward(result)),close

为什么要定义UDF、UDTF?

自定义函数可以埋点Log打印日志,方便调试。

引入第三方jar包时,也需要。

七、窗口函数

1)Rank

(1)RANK()排序相同时会重复,总数不会变

(2)DENSE_RANK()排序相同时会重复,总数会减少

(3)ROW_NUMBER()会根据顺序计算

学生姓名分数
小明90
小红85
小王90
小李85

使用上述三种窗口函数对该数据进行排序:

  1. 使用 RANK():
    • 小明:1 (90分)
    • 小王:1 (90分)
    • 小红:3 (85分)
    • 小李:3 (85分)
  2. 使用 DENSE_RANK():
    • 小明:1 (90分)
    • 小王:2 (90分)
    • 小红:3 (85分)
    • 小李:4 (85分)
  3. 使用 ROW_NUMBER():
    • 小明:1 (90分)
    • 小红:2 (85分)
    • 小王:3 (90分)
    • 小李:4 (85分)

2)OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化

(1)current row,当前行

(2)n preceding,往前n行数据

(3)n FOLLOWING,往后n行数据

(4)UNBOUNDED:起点。unbounded preceding:表示从前面的起点,unbounded following表示到后面的终点

(5)lag(col,n):往前第n行数据

(6)lead(col,n):往后第n行数据

(7)NTILE(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。n必须为int类型。

八、Hive优化

1)MapJoin

如果发生数据倾斜,可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。

如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成Join。

2)行列过滤

列处理:在select中,只拿需要的列,如果有,尽量使用分区过滤,不用select *。

行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在where后面,那么就会先全表关联,之后再过滤。

(例如执行连接时,如果客户表非常大,连接完成后再查询会很慢)

SELECT o.order_id, o.order_date, c.customer_name
FROM orders o
LEFT OUTER JOIN customers c ON o.customer_id = c.customer_id AND c.customer_region = 'Asia';

通过这种方式,查询引擎会在进行外连接时就会考虑到客户地区为亚洲的条件,只关联符合条件的客户信息,避免了不必要的数据传输和处理,提高了查询效率。

3)列式过滤

当Hive执行查询时,如果查询中包含了过滤条件,例如WHERE子句,Hive会尝试将这些条件推送到存储系统中(例如HDFS),让存储系统在读取数据时就进行过滤。

4)采用分区技术

在Hive中,通过对表进行分区,将表的数据按照某个列的取值范围或者特定的分区规则进行划分,例如按照日期、地区等字段进行分区。通过合理地选择分区字段,可以将数据分散存储在不同的分区目录中,从而实现更高效的数据访问。

5)合理设置Map数(设置数据的最小分隔单元、最大分隔单元大小。减少max可以增加map数,增大max可以减少map数)

直接跳转mared.map.tasks这个参数是没有效果的

6)合理设置Reduce数

Reduce个数并不是越多越好

(1)过多的启动和初始化Reduce也会消耗时间和资源

(2)有多少个Reduce,就会有多少个输出文件,如果生成了很多小文件,那么如果这些小文件作为下一个任务的输入,也会出现小文件过多的问题。

在设置Reduce个数的时候,也要考虑两个原则:处理大数据量利用合适的Reduce数,使单个Reduce任务处理数据量大小要合适。

7)小文件如何产生的?

(1)动态分区插入数据(如果数据量较大,可能会导致每个分区生成一个文件,如果分区数量较多,就会产生大量的小文件),产生大量的小文件,从而导致map数量剧增;(需要合理设置分区数量,合并、清理产生的小文件,批量插入数据)

(2)reduce数量越多,小文件就越多。

(3)数据源本身就包含大量的小文件。

8)小文件解决方案

(1)在Map执行前合并小文件,减少Map(CombineHiveInputFormat具有对小文件合并的功能(系统默认的格式))

​ HiveInputFormat没有对小文件合并的功能。

(2)merge 输出合并小文件

SET hive.merge.mapfiles = true;-- 默认true,在map-only任务结束时合并 小文件

SET hive.merge.mapredfiles = true;-- 默认false,在map-reduce任务结 束时合并小文件 SET hive.merge.size.per.task = 268435456;-- 默认256M

SET hive.merge.smallfiles.avgsize = 16777216;-- 当输出文件的平均大小 小于16m该值时,启动一个独立的map-reduce任务进行文件merge

(3)开启JVM重用

set mapreduce.job.jvm.numtasks=10

9)开启map端combiner(不影响最终业务逻辑)

set hive.map.aggr=true;(map端局部聚合)

10)压缩(选择快的)

设置map端输出、中间结果压缩。(不完全是解决数据倾斜的问题,但是减少了IO读写和网络传输,提高效率)

set hive.exec.compress.intermediate=true–启用中间数据压缩

set mapreduce.map.output.compress=true–启用最终数据压缩

set mapreduce.map.outout.compress.codec=…;–设置压缩方式

11)采用spark引擎

九、Hive解决数据倾斜的方法

1)数据倾斜产生的原因

(1)不同数据类型关联产生数据倾斜

情形:比如用户表中user_id字段为int,log表中user_id字段string 类型。当按照user_id 进行两个表的Join操作时。(系统在比较时需要进行额外的数据类型转换操作。这样可能会影响计算的性能,并且可能导致数据分布不均匀。)

原因:

对两个表进行关联操作,由于数据类型不匹配,比如在哈希计算时,整数类型的数据和字符串类型的数据可能会得到不同的哈希值。假设用户表中的user_id范围是1到100,而日志表中的user_id是以字符串形式存储的,其中很多是以字母开头的,比如"abc123"、"xyz456"等。在进行哈希计算时,整数类型的user_id会得到一个连续的哈希值分布,比如1到100,而字符串类型的user_id则可能会得到一个离散的哈希值分布,因为字符串的哈希计算通常会考虑每个字符的ASCII码值。这样一来,在关联操作中,具有相同user_id的记录可能会被分配到不同的节点或任务进行处理,导致了数据分布不均匀的情况。

因此,数据类型不匹配可能会导致在关联操作中出现数据分布不均匀的情况,从而引发数据倾斜的问题。

解决方式:

把数字类型转换成字符串类型 select * from users a left outer join logs b on a.usr_id = cast(b.user_id as string)

(2)控制空值分布

生产环境中经常用大量空值数据进入到一个reduce中去,导致数据倾斜。

解决方法:自定义分区,将空的key转变为字符串加随机数,将因空值而造成倾斜的数据分布到多个Reducer中。

可以的话,过滤一下异常值。

2)解决数据倾斜的方法?

(1)group by

注:group by 优于 distinct group

解决方式:采用sum() group by的方式替换count(distinct)完成计算

count(distinct)操作会导致比较大的计算开销,特别是当数据量较大时。因为它需要对所有不同的值进行一次扫描,然后计算其数量。

(2)mapjoin

可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。

(3)开启数据倾斜时负载均衡

set hive.groupby.skewindata=true;

思想:就是先随机分发并处理,再按照Key group by处理

第一个MRJob中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分 聚合操作,并输出结果,这样处理的结果是相同的GroupByKey有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;

第二个MRJob再根据预处理的数据结果按照GroupByKey分布到Reduce中(这个过程可以保证相同的原始GroupByKey被分布到同一个Reduce中),最后完成最终的聚合操作。

点评:它使计算变成了两个mapreduce,先在第一个中在shuffle过程partition时随机给key打标记,使每个key随机均匀分布到各个reduce上计算,但是这样只能完成部分计算, 因为相同key没有分配到相同reduce上。 所以需要第二次的mapreduce,这次就回归正常shuffle,但是数据分布不均匀的问题在第一次mapreduce已经有了很大的改善,因此基本解决数据倾斜。因为大量计算已经在第一 次mr中随机分布到各个节点完成。

(4)设置多个reduce个数

十、Hive里字段的分隔符用的什么?为什么用\t?有遇到过字段里用\t的情况吗,怎么处理的?

hive 默认的字段分隔符为ascii码的控制符\001(^A),建表的时候用fieldsterminatedby ‘\001’。注意:如果采用\t或者\001等为分隔符,需要要求前端埋点和javaEE后台传递过来 的数据必须不能出现该分隔符,通过代码规范约束。一旦传输过来的数据含有分隔符,需要在前一级数据中转义或者替换(ETL)。

可以设置参数(导入HDFS同样有效):

–hive-drop-import-delims 导入到 hive 时删除 \n, \r, \001

–hive-delims-replacement 导入到 hive 时用自定义的字符替换掉 \n,\r,\001

十一、Tez引擎优点?

Tez可以将多个有依赖的作业转换为一个作业,这样只需要写一次HDFS,且中间节点较少,从而大大提升作业的计算性能。

Mr/tez/spark区别:

Mr引擎:多job串联,基于磁盘,落盘的地方比较多。虽然慢,但一定能跑出结果。一般处理,周、月、年指标。

Spark引擎:虽然在Shuffle过程中也落盘,但是并不是所有算子都需要Shuffle,尤其是多算子过程,中间过程不落盘DAG有向无环图。兼顾了可靠性和效率。一般处理天指标。

Tez 引擎:完全基于内存。 注意:如果数据量特别大,慎重使用。容易OOM。一般用于快速出结果,数据量比较小的场景。

十二、MySql元数据备份

1)元数据备份,如果遇到数据损坏,可能整个集群无法正常运行,至少要保证每日零点之后备份到其它服务器两个副本(可以在Keepalived配置文件中添加脚本,定期执行MySQL备份命令,并将备份文件同步到备用节点上。)

编写备份脚本 backup_mysql.sh

#!/bin/bash

# 这里是你执行MySQL备份的命令,可以使用mysqldump或其他备份工具
mysqldump -u username -p --all-databases > /path/to/backup/mysql_backup.sql

修改Keepalived的配置文件(通常是/etc/keepalived/keepalived.conf),添加一个vrrp_script来执行备份脚本:

vrrp_script backup_mysql {
    script "/path/to/backup_mysql.sh"
    interval 1800  # 每隔1800秒(30分钟)执行一次备份
}

这里的backup_mysql是脚本的名字,可以自定义。interval参数指定了脚本执行的间隔时间,单位是秒。

在Keepalived的主配置中,将这个脚本添加到vrrp_instance中的vrrp_script项中:

vrrp_instance VI_1 {
    ...
    # 添加脚本到vrrp_script项中
    vrrp_script backup_mysql
    ...
}

保存并退出配置文件,然后重新加载或重启Keepalived服务,以使更改生效。

# 重新加载配置
sudo systemctl reload keepalived

# 或者重启服务
sudo systemctl restart keepalived

2)MySql utf8超过字节数问题

MySQL 的utf8 编码最多存储3个字节,当数据中存在表情号、特色符号时会占用超过 3 个字节数的字节,那么会出现错误 Incorrectstringvalue: ‘\xF0\x9F\x91\x91\xE5\xB0…’ 解决办法:将utf8修改为utf8mb4

十三、Union与Union all区别

1)union会将联合的结果集去重,效率较union all差

2)union all不会对结果集去重,所以效率高

  • 18
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值