hive专题面试总结

发布于:2025-07-30 ⋅ 阅读:(36) ⋅ 点赞:(0)

一、自定义过hiveudf函数吗?hive中的udf函数有几种?

        UDF(User-Defined Function)是 Hive 中允许用户扩展内置函数的机制,通过编写自定义代码实现特定的数据处理逻辑。与 SQL 内置函数(如 SUMSUBSTRING)不同,UDF 可以实现更灵活、复杂的功能。

Hive 支持三种 UDF:

  1. UDF(普通函数):输入一行,输出一行(一对一,比如将字符串转成大写)。

  2. UDAF(聚合函数):输入多行,输出一行(多对一,比如计算一组数字的平均值)。

  3. UDTF(表生成函数):输入一行,输出多行(一对多,比如按逗号分割拆分字符串,一行转多行)

二、hive的几种建表方式

hive创建表有几种方式,其区别是什么?

1)create table

        这是最基础的建表方式,需要手动指定表的列名、数据类型、存储格式等结构信息,并且不会自动填充数据。如果要填充数据,后续需要通过INSERT INTOLOAD DATA 或 HDFS PUT 等操作。

2)create table as select...

        该方式会根据SELECT语句的查询结果创建一个新表,并将查询结果数据填充到新表中。新表的列名和数据类型会根据SELECT语句中的字段自动推断。

3)create table like tablename1;

        这种方式会创建一个新表,新表的结构(包括列名、数据类型、分区、分桶等定义)与指定的已存在表完全相同,但不会复制已存在表中的数据。后续如果需要填充数据,同样需要使用INSERT INTOLOAD DATA 等操作。

不同方式的区别

1)create table 创建表,需要明确指定表结构和索引;

2)create table as 创建表,只有表结构,没有索引;

3)create table like 创建表,创建出来的新表包含源表的完整结构及索引信息;

建表方式 是否需要手动指定结构 是否复制数据 灵活性 适用场景
create table 是,需详细指定 否,需后续手动填充 高,可精细控制表结构、存储格式等 已知表结构,对表结构有精细控制需求
create table as select... 否,根据查询结果自动推断 是,根据查询结果填充数据 中,存储格式依赖于源表 基于已有数据查询结果快速创建新表
create table like tablename1 否,复制已有表结构 否,需后续手动填充 中,结构固定但可灵活填充数据 快速创建与已有表结构相同的新表

三、数据库中的NULL在hive中如何存储?

简要描述数据库中的null,说出null在hive底层如何存储?

并解释select a.* from t1 a left outer join on t2 b on a.id = b.id where b.id is null;语句的含义?

        在数据库中,NULL 代表缺失值或未知值,它和空字符串("" )、零值(例如数值类型中的 0 )是不同的概念。

        空字符串:是一个确定的、有长度为 0 的字符数据。

        零值:是具体数据类型(如整型、浮点型等)中的一个确定数值。

   NULL:表示数据未知、未赋值或者不存在,它参与运算时,会使结果也通常为 NULL

hive表中默认将NULL存为\N

表t1别名是a,表t2别名是b,根据id字段做左外连接,查询出b.id为null的值

四、collect_list()和collect_set的区别(行转列)

hive中,collect_list(),collect_set()两个函数的区别是什么?参数类型有什么限制?

        hive中collect相关的函数有collect_list和collect_set,它们都是将分组中的某列转为一个数组相返回,不同的是collect_list不去重,而collect_set去重

        collect_list(col)函数将分组内指定列的所有值按原始顺序保留重复值,聚合为一个数组,只接受基本数据类型,它的主要作用是将某字段的值进行汇总,产生array类型字段

        特点:保留重复元素,维持元素在原始数据中的顺序

        collect_set(col)函数将分组内指定列的所有值去重后,聚合为一个无固定顺序的数组,只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段

        特点:自动去除重(相同值只保留一个)元素顺序不固定(无法保证与原始数据顺序一致)

五、hive查询内存溢出如何解决

        hive在select查询数据后,执行insert操作插入ORC表和parquet表操作的过程中,遇到over gclimit、java.lang.OutMemoryError:java heap space等字样的错误,大概从那些地方查找原因解决问题?

1)可能数据分布不均匀造成的,可以在select阶段加cluster by rand()让数据均匀分布

2)map和reduce阶段的内存不够,通过hive参数增加内存

set mapreduce.reduce.memory.mb=16384;(实际调试的时候,8G内存不够,增加到16G解决问题)表示每个 Reduce 任务最多可使用 16GB 内存

set mapreduce.map.memory.mb = 4096;表示每个 Map 任务最多可使用 4GB 内存

3)另外在数据格式不统一的情况下,不同格式的insert 操作效率奇低

六、hive 4种by操作的区别与联系(重点)

hive中order by 、distribute by 、sort by 和cluster by的区别和联系?

        order by 会对数据进行全局排序,和oracle 和 mysql等数据库中的order by 效果一样,它只在一个reduce中进行,所以数据量特别大的时候效率非常低。而且当设置:set hive.mapred.mode=strict的时候不指定limit,执行select会报错,如下:LIMIT must also be specified.

        sort by是单独在各自的reduce中进行排序,所以并不能保证全局有序,一般和distribute by一起执行,而且distribute by 要写在sort by 前面,如果mapred.reduce.tasks=1和order by效果一样,如果大于1会分成几个文件输出每个文件会按照指定的字段排序,而不保证全局有序。sort by不受hive.mapred.mode是否为strict,nostrict的影响。mapred.reduce.tasks=1 是强制指定 1 个 Reduce 任务处理数据,适用于需要全局汇总或结果合并为单个文件的场景。

        distribute by 会对指定的字段按照hashCode值对reduce的个数取模,然后将任务分配到对应的reduce中去执行,也就是在mapreduce程序中的patition分区过程。默认根据指定key.hashCode()$lnteger.MAX_VALUE%numReduce确定处理该任务的reduce。

        cluster by distribute by 和sort by 合用就相当于cluster by,但是cluster by不能指定排序为asc或desc的规则,只能是desc倒序排列

七、hive性能调优 

详细的在我的上一篇文章hive的相关的优化

hive性能调优的常见方法?

1、hive层面优化

1)利用分区表优化

2)利用分桶表优化

3)join优化

4)Group By数据倾斜优化解决这个问题的方法是配置一个参数:set hive.groupby.skewindata=true

        当group by的 Key 分布不均(某 Key 对应数据量极大)时,设置set hive.groupby.skewindata=true后,Hive 会将查询拆分为两次 MapReduce:第一次随机分发数据并局部聚合,第二次按原 Key 聚合,避免单 Reduce 处理过多数据。

5)Order By优化

   Order By会将所有数据发送到一个 Reduce 进行全局排序,效率低;

        替代方案:用Sort By(每个 Reduce 内排序)+Distribute By(按指定列分发到不同 Reduce),实现局部有序,提升效率;若需全局有序,可结合Limit限制返回条数,减少排序数据量

6)一次读取多次插入

7)join字段显示类型转换

        若两表 Join 的字段类型不一致(如一个是string,一个是int),需显式转换为相同类型(如cast(col as string)),避免 Hive 隐式转换导致的全表扫描或数据不匹配

2、hive架构层面优化

1)不执行MapReduce

        对于简单查询(如select * from table limit 10),通过set hive.fetch.task.conversion=more让 Hive 直接读取数据文件返回结果,跳过 MapReduce 阶段,提升响应速度。

2)本地模式执行MapReduce

        小数据集查询时,开启本地模式(set hive.exec.mode.local.auto=true),让 MapReduce 任务在单节点本地执行,避免集群资源调度开销,加速小任务运行(默认适用于数据量小于 128MB、Map 数小于 4 的任务)。

3)JVM重(chong)用

        通过set mapreduce.job.jvm.numtasks=N(N 为整数)设置一个 JVM 实例可执行的 Map/Reduce 任务数,减少 JVM 启动和销毁的开销(尤其适合小文件多、任务数量多的场景)

4)并行化

        对于包含多个独立子查询(如union all、多表插入)的 SQL,设置set hive.exec.parallel=trueset hive.exec.parallel.thread.number=N(N 为并行线程数),让子查询并行执行,缩短总耗时。

3、底层MapReduce优化

1)合理设置map数

        避免 map 数过多:小文件过多时,通过CombineHiveInputFormat合并小文件(set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat),减少 map 数,降低资源调度开销;

        避免 map 数过少:大文件拆分时,通过mapreduce.input.fileinputformat.split.minsizemapreduce.input.fileinputformat.split.maxsize调整 split 大小,确保每个 map 处理的数据量适中(通常 128MB~1GB)。

2)合理设置Reduce数

        手动指定:通过set mapreduce.job.reduces=N(N 为 Reduce 数)设置,通常根据数据量(每个 Reduce 处理 1~2GB 数据)或集群资源调整;

        自动调整:开启hive.exec.dynamic.partition=truehive.exec.dynamic.partition.mode=nonstrict,让 Hive 根据数据量动态计算 Reduce 数,避免 Reduce 数过多(资源浪费)或过少(数据倾斜)

八、hive包含哪些join操作

hive的join有几种方式,怎么实现join的?

1、hive中常见的join方式

        hive中除了支持和传统数据库中一样的内关联、左关联、右关联、全关联、还支持left semi join和cross join,但这两种join类型也可以用前面的代替

2、如何实现join?

        1)内关联(join)只返回能关联上的结果,select a.id,a.name,b.age from djt_a a join djt_b b on (a.id = b.id);

        2)左外关联(left [outer] join)以left [outer] join关键字前面的表作为主表,和其他表进行关联,返回记录和主表的记录数一致,关联不上的字段设置为NULL。是否指定outer关键字,对查询结果无影响。

select a.id,a.name,b.age from djt_a left join djt_b b on (a.id = b.id);

        3)右外关联(right [outer] join)和左外关联相反,以right [outer] join 关键词后面的表作为主表,和前面的表做关联,返回记录数和主表一致,关联不上的字段为NULL。是否指定outer关键字,对查询结果无影响;

        4)全外关联(full [outer] join)以两个表的记录为基准,返回两个表的记录去重之和,关联不上的字段为NULL。是否指定outer关键字无影响,注意:full join时候,hive不会使用Mapjoin来优化;

        5)left semi join以left semi join关键字前面的表为主表,返回主表的key也在副表中的记录

left semi join与left join的区别?(重点)

left semi join(左半连接)是in/exists子查询的一种更高级的实现。

   left join:以左表为主表,返回左表所有记录 + 右表中匹配关联条件的记录;右表无匹配时,用 NULL 填充。

   left semi join:仅返回左表中与右表存在匹配关系的记录(类似 in 或 exists 子查询),且只保留左表字段。

1、left semi join join子句中右边的表只能在on子句中设置过滤条件;

2、left semi join中最后的select的结果只许出现左表;

3、因为left semi join是in(keySet)的关系,遇到右表重复记录,左表会跳过,仅仅只返回一条记录,而join则会一直遍历。

6)笛卡尔积关联(cross join)返回两个表的笛卡尔积结果,不需要指定关联键

九、hive内部表和外部表

hive内部表和外部表的区别?应该如何选择使用哪种表呢?

        1)hive向内部表导入数据时,会将数据移动到数据仓库指向的路径;若是外部表,数据的具体存放目录由用户建表时指定,在导入数据到外部表,数据并没有移动到自己的数据仓库目录下,也就是说外部表中的数据并不是由它自己来管理的!而内部表则不一样

        2)在删除内部表的时候,hive将会把属于表的元数据和数据全部删掉;而删除外部表的时候,hive仅仅删除外部表的元数据,数据是不会删除的!那么,应该如何选择使用哪种表呢?在大多数情况没有太多的区别,因此选择只是个人喜好的问题。但是如果所有处理都需要由hive完成,那么你应该创建内部表,否则使用外部表!外部表相对来说更加安全些,数据组织也更加灵活,方便共享元数据


网站公告

今日签到

点亮在社区的每一天
去签到