1.大表join小表产生的问题,怎么解决?

mapjoin方案

  1. join因为空值导致长尾(key为空值是用随机值代替)
  2. join因为热点值导致长尾,也可以将热点数据和非热点数据分开处理,最后合并

2.udf udaf udtf区别

  • UDF操作作用于单个数据行,并且产生一个数据行作为输出。大多数函数都属于这一类(比如数学函数和字符串函数)。
  • UDAF 接受多个输入数据行,并产生一个输出数据行。像COUNT和MAX这样的函数就是聚集函数。
  • UDTF 操作作用于单个数据行,并且产生多个数据行——-一个表作为输出。lateral view explore()

简单来说:

  • UDF:返回对应值,一对一
  • UDAF:返回聚类值,多对一
  • UDTF:返回拆分值,一对多

3.hive有哪些保存元数据的方式,个有什么特点。

  • 内存数据库derby,安装小,但是数据存在内存,不稳定
  • mysql数据库,数据存储模式可以自己设置,持久化好,查看方便。

4.hive内部表和外部表的区别

  • 内部表:加载数据到hive所在的hdfs目录,删除时,元数据和数据文件都删除
  • 外部表:不加载数据到hive所在的hdfs目录,删除时,只删除表结构。

这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。

5.生产环境中为什么建议使用外部表?

  • 因为外部表不会加载数据到hive,减少数据传输、数据还能共享。
  • hive不会修改数据,所以无需担心数据的损坏
  • 删除表时,只删除表结构、不删除数据。

6.insert into 和 insert overwrite区别?

  • insert into:将数据追加写到表中
  • insert overwrite:覆盖之前的内容,先删除分区或表数据在写入

7.hive的判断函数有哪些

hive 的条件判断(if、coalesce、case)

8.简单描述一下HIVE的功能?用hive创建表有几种方式?hive表有几种?

  • hive主要是做离线分析的,把hiveSQL转换成mapreduce程序,提交到yarn集群上运行,简化了mr程序的开发。

hive建表有三种方式

  1. 直接建表法
  2. 查询建表法(通过AS 查询语句完成建表:将子查询的结果存在新表里,有数据,一般用于中间表)
  3. like建表法(会创建结构完全相同的表,但是没有数据)

hive表有2种:内部表和外部表

9.union all和union的区别

  • union 去重
  • union oll 不去重

10.如何解决hive数据倾斜的问题

1.group by

注:group by 优于 distinct

  • 情形:group by 维度过小,某值的数量过多
  • 后果:处理某值的 reduce 非常耗时
  • 解决方式:采用 sum() group by 的方式来替换 count(distinct)完成计算。

2.count(distinct)

count(distinct xx)

  • 情形:某特殊值过多
  • 后果:处理此特殊值的 reduce 耗时;只有一个 reduce 任务
  • 解决方式:count distinct 时,将值为空的情况单独处理,比如可以直接过滤空值的行,
  • 在最后结果中加 1。如果还有其他计算,需要进行 group by,可以先将值为空的记录单独处理,再和其他计算结果进行 union。

3.mapjoin

采用mapjoin方法,在map时候进行关联,适用于小表

4.不同数据类型关联产生数据倾斜

  • 情形:比如用户表中 user_id 字段为 int,log 表中 user_id 字段既有 string 类型也有 int 类型。当按照 user_id 进行两个表的 Join 操作时。

  • 后果:处理此特殊值的 reduce 耗时;只有一个 reduce 任务

    默认的 Hash 操作会按 int 型的 id 来进行分配,这样会导致所有 string 类型 id 的记录都分配到一个 Reducer 中。

  • 解决方式:把数字类型转换成字符串类型

1
2
3
4
select * 
  from users a
  left outer join logs b
    on a.usr_id = cast(b.user_id as string)

5.开启数据倾斜时负载均衡

  • set hive.groupby.skewindata=true;
  • 思想:就是先随机分发并处理,再按照 key group by 来分发处理。
  • 操作:当选项设定为 true,生成的查询计划会有两个 MRJob。

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

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

点评:它使计算变成了两个 mapreduce,先在第一个中在 shuffle 过程 partition 时随机给 key 打标记,使每个 key 随机均匀分布到各个 reduce 上计算,但是这样只能完成部分计算,因为相同 key 没有分配到相同 reduce 上。

所以需要第二次的 mapreduce,这次就回归正常 shuffle,但是数据分布不均匀的问题在第一次 mapreduce 已经有了很大的改善,因此基本解决数据倾斜。因为大量计算已经在第一次mr 中随机分布到各个节点完成。

6.控制空值分布

将为空的 key 转变为字符串加随机数或纯随机数,将因空值而造成倾斜的数据分不到多个 Reducer。

注:对于异常值如果不需要的话,最好是提前在 where 条件里过滤掉,这样可以使计算量大大减少

11.hive性能优化常用的方法

1. MapJoin

如果不指定 MapJoin 或者不符合 MapJoin 的条件,那么 Hive 解析器会将 Join 操作转换成 Common Join,即:在 Reduce 阶段完成 join。容易发生数据倾斜。可以用 MapJoin 把小表全部加载到内存在 map 端进行 join,避免 reducer 处理。

2.行列过滤

  • 列处理:在 SELECT 中,只拿需要的列,如果有,尽量使用分区过滤,少用 SELECT *。
  • 行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在 Where 后面,那么就会先全表关联,之后再过滤。

3.列式存储

parquet,ORCFile

4.采用分区技术

partition(ptime=20210321070000)

5.合理设置 Map 数

  1. 通常情况下,作业会通过 input 的目录产生一个或者多个 map 任务。

    主要的决定因素有:input 的文件总个数,input 的文件大小,集群设置的文件块大小。

  2. 是不是 map 数越多越好?

    答案是否定的。如果一个任务有很多小文件(远远小于块大小 128m),则每个小文件也会被当做一个块,用一个 map 任务来完成,而一个 map 任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的 map 数是受限的。

  3. 是不是保证每个 map 处理接近 128m 的文件块,就高枕无忧了?

    答案也是不一定。比如有一个 127m 的文件,正常会用一个 map 去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果 map 处理的逻辑比较复杂,用一个 map任务去做,肯定也比较耗时。

针对上面的问题 2 和 3,我们需要采取两种方式来解决:即减少 map 数和增加 map 数;

6.小文件进行合并

在 Map 执行前合并小文件,减少 Map 数:

  • CombineHiveInputFormat 具有对小文件进行合并的功能(系统默认的格式)。
  • HiveInputFormat 没有对小文件合并功能。

7.合理设置 Reduce 数

Reduce 个数并不是越多越好

1. 过多的启动和初始化 Reduce 也会消耗时间和资源;
2. 另外,有多少个 Reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;

在设置 Reduce 个数的时候也需要考虑这两个原则:

  • 处理大数据量利用合适的 Reduce数;
  • 使单个 Reduce 任务处理数据量大小要合适;

8.常用参数

1
2
3
4
5
6
// 输出合并小文件
SET hive.merge.mapfiles = true; -- 默认 true,在 map-only 任务结束时合并小文件
SET hive.merge.mapredfiles = true; -- 默认 false,在 map-reduce 任务结束时合并小文件
SET hive.merge.size.per.task = 268435456; -- 默认 256M
-- 当输出文件的平均大小小于 16m 该值时,启动一个独立的 map-reduce 任务进行文件 merge
SET hive.merge.smallfiles.avgsize = 16777216; 

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

1
set hive.map.aggr=true

10.压缩(选择快的)

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

11.开启 JVM 重用

13.简述delete,drop,truncate的区别

  • delet 删除数据
  • drop 删除表
  • truncate 摧毁表结构并重建

14.四个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。

15.分区分桶的区别,为什么要分区

  • 分区表:原来的一个大表存储的时候分成不同的数据目录进行存储。如果说是单分区表,那么在表的目录下就只有一级子目录,如果说是多分区表,那么在表的目录下有多少分区就有多少级子目录。不管是单分区表,还是多分区表,在表的目录下,和非最终分区目录下是不能直接存储数据文件的
  • 分桶表:原理和hashpartitioner 一样,将hive中的一张表的数据进行归纳分类的时候,归纳分类规则就是hashpartitioner。(需要指定分桶字段,指定分成多少桶)

分区表和分桶的区别除了存储的格式不同外,最主要的是作用:

  • 分区表:细化数据管理,缩小mapreduce程序 需要扫描的数据量。

  • 分桶表:提高join查询的效率,在一份数据会被经常用来做连接查询的时候建立分桶,分桶字段就是连接字段;提高采样的效率。

16.group by为什么要排序

20.手写sql,连续5天活跃用户?