大厂Hive面试题集锦及参考答案
请描述 Hive 的架构,包括各个组件的功能和它们之间的交互关系。
Hive 架构主要由以下组件构成,协作完成 SQL 到 MapReduce/Tez 任务的转换:
- 用户接口(CLI/Web UI/JDBC):提供命令行、浏览器或编程接口(如 Java)提交查询。
- Driver:会话管理器:接收用户查询,维护会话上下文。编译器调用:将 SQL 传递给编译器生成执行计划。
- 编译器(Compiler):解析与优化:将 SQL 转换为抽象语法树(AST),优化后生成逻辑计划和物理计划(如 MapReduce 任务)。
- 元数据存储(Metastore):存储表结构:包括列名、数据类型、分区信息等,通常使用 MySQL 或 PostgreSQL 实现。
- 执行引擎(Execution Engine):任务调度:将物理计划提交给 Hadoop 集群(如 YARN)执行。监控与回调:跟踪任务状态,返回结果给用户。
交互流程:
- 用户通过 CLI 提交
SELECT * FROM table;
。 - Driver 调用编译器解析 SQL,向 Metastore 获取表结构。
- 编译器生成 MapReduce 任务,由执行引擎提交到集群。
- 集群执行完成后,结果返回给用户接口。
Hive 有哪些表?内部表与外部表在数据存储位置、数据管理方式、使用场景等方面有哪些区别?分别在什么情况下使用内部表和外部表?
Hive 的表分为内部表(Managed Table)和外部表(External Table),两者的核心差异体现在数据生命周期管理和存储位置的控制上。
- 数据存储位置内部表:Hive 完全控制数据存储路径。创建表时,若未指定路径,数据默认存储在 Hive 配置的仓库目录(如 /user/hive/warehouse)下。外部表:数据存储路径由用户指定,且 Hive 不会强制将数据移动到仓库目录。外部表仅记录元数据,实际数据可位于 HDFS 或云存储的任意位置。
- 数据管理方式内部表:删除表时,Hive 会同时删除元数据和底层数据。这意味着数据会被永久删除,需谨慎操作。外部表:删除表时,Hive 仅删除元数据,而实际数据仍保留在原始路径中。这使得外部表更适合需要多系统共享数据的场景。
- 使用场景内部表适用于临时或中间数据。例如,ETL 过程中的中间表,或不需要长期保留的实验性数据。外部表适用于共享数据或已有数据。例如,当数据需要被 Spark、Presto 等其他工具访问时,或数据已存在于 HDFS 中且不希望被 Hive 管理时。
关键选择依据:是否需要 Hive 管理数据生命周期。若希望删除表时自动清理数据,选内部表;若需保留数据,或与其他系统共享,选外部表。
请详细说说 Hive 的数据倾斜,包括产生的原因、表象以及常见的解决方案。
数据倾斜是分布式计算中的典型问题,表现为部分任务处理的数据量远高于其他任务,导致任务执行时间过长甚至失败。
★ 产生原因 ★
- 数据分布不均:某些 Key 的值集中(如空值、枚举值),导致 Shuffle 后数据分布倾斜。
- 业务逻辑特性:例如按城市分组统计时,超大城市的数据量远高于其他城市。
- 表连接或聚合操作:如大表 Join 小表时,小表的某些 Key 在大表中大量重复。
★ 表象 ★
- 任务进度长时间卡在 99%,个别 Reduce 任务未完成。
- 监控界面显示个别节点的处理数据量是其他节点的数倍。
- 日志中频繁出现 GC 超时或 OOM 错误。
★ 解决方案 ★
- 预处理数据:过滤无效值(如 NULL),或对倾斜 Key 单独处理。
- 调整 SQL 逻辑: Map Join:将小表广播到所有 Map 端,避免 Shuffle。需设置 hive.auto.convert.join=true。随机数打散:对倾斜 Key 添加随机前缀,分散数据到不同 Reduce 节点。
- 参数调优: 开启负载均衡:hive.groupby.skewindata=true 自动对 Group By 操作做两阶段聚合。增加 Reduce 数量:通过 set mapred.reduce.tasks=N 调整。
- 使用中间表:将倾斜数据与非倾斜数据拆分处理,再合并结果。
你做过 Hive 优化吗?请详细说明 Hive 优化的常见方法和具体实践。
Hive 优化的核心目标是降低资源消耗并提升查询速度,需从数据存储、计算逻辑和资源配置三方面入手。
1. 数据存储优化
- 分区与分桶: 分区表:按日期、地区等字段分区,避免全表扫描。例如:分桶表:对字段哈希分桶,优化 Join 和采样查询。需指定分桶数量和字段:
- 存储格式:使用列式存储(ORC、Parquet),结合压缩算法(Snappy、Zlib)减少 IO。
2. 计算逻辑优化
- 谓词下推:通过
hive.optimize.ppd=true
提前过滤数据。 - 合并小文件:通过
hive.merge.mapfiles=true
减少 Map 任务数。 - 避免笛卡尔积:确保 Join 操作有明确的关联条件。
3. 资源与参数调优
- 并行执行:设置
hive.exec.parallel=true
允许多阶段任务并行。 - 调整 Map/Reduce 数量:根据数据量动态分配资源,避免过多或过少任务。
- JVM 重用:通过
hive.mapred.reduce.tasks.speculative.execution=false
避免重复任务。
4. 统计信息收集
- 执行
ANALYZE TABLE table_name COMPUTE STATISTICS
帮助优化器生成更优执行计划。
Hive 的存储格式有哪些?它们各自的特点和适用场景是什么?
Hive 支持多种存储格式,不同格式在压缩率、查询性能和可分割性上表现各异。
TextFile |
默认格式,纯文本,可读性强;不支持压缩,存储和查询效率低。 |
数据交换或临时存储 |
SequenceFile |
二进制格式,支持记录级压缩;可分割,适合存储键值对数据。 |
MapReduce 中间结果存储 |
ORC |
列式存储,高压缩率(ZLIB/ZStandard),支持谓词下推和索引。 |
复杂查询、OLAP 场景 |
Parquet |
列式存储,支持嵌套数据结构,兼容多种计算框架(Spark、Impala)。 |
多系统协作、嵌套数据场景 |
Avro |
基于 Schema 的二进制格式,支持动态模式演化,适合数据序列化。 |
数据序列化与反序列化场景 |
关键选择建议:
- 若需高压缩和快速查询,优先选择 ORC 或 Parquet。
- 若需跨平台兼容性,Parquet 是更通用的选择。
- 若数据需要频繁读写或人工查看,可保留 TextFile。
Hive 和 MySQL 在数据存储、查询语言、数据处理能力、应用场景等方面有哪些区别?
Hive 与 MySQL 是两类不同定位的系统,核心差异如下:
1. 数据存储
- Hive:数据存储在分布式文件系统(如 HDFS)中,支持 PB 级数据,无事务支持,** schema-on-read**(读取时校验数据格式)。
- MySQL:数据存储在本地磁盘或网络存储,支持 ACID 事务,schema-on-write(写入时严格校验格式)。
2. 查询语言
- Hive:使用 HQL(类 SQL),但底层转换为 MapReduce 或 Tez 任务,延迟高(分钟级)。
- MySQL:支持标准 SQL 和复杂查询(如子查询、窗口函数),响应快(毫秒级)。
3. 数据处理能力
- Hive:专为批处理设计,适合全表扫描和聚合操作,但不支持实时更新和删除。
- MySQL:支持实时增删改查(CRUD),适合低延迟的 OLTP 场景。
4. 应用场景
- Hive:用于数据仓库、离线分析(如日志分析、报表生成)。
- MySQL:用于在线业务系统(如用户管理、订单处理)。
5. 扩展性
- Hive:通过 Hadoop 生态横向扩展,可处理海量数据。
- MySQL:垂直扩展(提升单机性能)或通过分库分表实现有限扩展。
Hive 的窗口函数有哪些?请分别说明它们的使用场景和作用,并举例说明。
Hive 的窗口函数(Window Functions)用于在特定数据窗口内执行计算,支持复杂的分组和排序操作。以下是常见窗口函数及其典型应用场景:
1. 排名函数
- ROW_NUMBER():为每一行分配唯一的连续序号,即使值相同也会区分。 场景:生成唯一排名,如用户行为日志按时间排序后标记顺序。
- RANK() 与 DENSE_RANK():按值排序后分配排名,但处理重复值的方式不同。 RANK():相同值共享排名,后续序号跳跃(如 1,1,3)。DENSE_RANK():相同值共享排名,后续序号连续(如 1,1,2)。场景:成绩排名中处理并列名次。
2. 聚合类窗口函数
- SUM()/AVG()/COUNT() OVER():在窗口内累加、平均或计数。 场景:计算累计销售额或移动平均。
3. 偏移函数
- LAG() 与 LEAD():访问当前行之前或之后的指定偏移量数据。 场景:分析用户连续登录天数或环比增长。
4. 分布函数
- NTILE(n):将数据分为
n
个近似相等的桶。 场景:将用户按消费金额分为高、中、低三组。
关键点:窗口函数通过 PARTITION BY
定义分组,ORDER BY
控制排序,ROWS/RANGE
指定窗口范围,灵活支持复杂分析需求。
在使用 Hive 时,数据会同步到 HDFS,针对小文件问题通常有哪些解决方法?
小文件问题指 HDFS 中存在大量小于块大小(如 128MB)的文件,导致元数据压力增大和计算效率降低。常见解决方案如下:
1. 合并已有小文件
- 输出阶段合并:通过 Hive 参数在任务结束时自动合并。
- 定期执行合并脚本:使用
ALTER TABLE table CONCATENATE
合并小文件(仅适用于 RCFile 或 ORC 格式)。
2. 写入时避免生成小文件
- 减少 Reduce 数量:合理设置
mapred.reduce.tasks
,避免过多的 Reduce 任务产生小文件。 - 使用动态分区优化:通过
hive.exec.dynamic.partition.mode=nonstrict
避免动态分区过多导致小文件。
3. 外部工具处理
- Hadoop Archive (HAR):将小文件打包为归档文件,减少 NameNode 负载,但读取时需额外解压。
- 使用 Spark 或 DistCP:通过其他计算框架预处理数据后再导入 Hive。
4. 存储格式优化
- 采用列式存储格式(如 ORC、Parquet),其高压缩率和块结构能减少小文件影响。
请详细描述 Hive Shuffle 的具体过程。
Shuffle 是 Hive 执行 MapReduce 任务时数据从 Map 阶段到 Reduce 阶段的传输过程,核心步骤包括:
- Map 阶段输出排序Map 任务将输出数据按 Key 进行分区(Partition),确保相同 Key 的数据进入同一 Reduce 任务。数据在 Map 端内存中按 Key 排序,并写入本地磁盘的临时文件。
- 溢写(Spill)与合并(Merge)当 Map 输出缓冲区达到阈值(mapreduce.task.io.sort.mb)时,数据会溢写到磁盘。多次溢写生成的临时文件会合并为一个已排序的大文件,减少后续传输开销。
- Fetch 阶段(数据拉取)Reduce 任务通过 HTTP 请求从各个 Map 任务的磁盘中拉取属于自己分区的数据。数据拉取后会在 Reduce 端再次排序合并,形成最终输入文件。
- 压缩优化若开启中间数据压缩(mapreduce.map.output.compress=true),Map 输出会以压缩格式传输,减少网络 IO。
性能瓶颈:Shuffle 的磁盘 IO 和网络传输是任务的主要耗时环节,合理设置分区数、压缩算法和内存参数可显著提升效率。
Hive 有哪些保存元数据的方式?这些方式各自的特点和适用场景是什么?
Hive 元数据存储方式决定了其多用户协作能力和部署复杂度,主要有以下三种:
内嵌 Derby |
默认模式,元数据存储在本地 Derby 数据库; 仅支持单会话访问 ,稳定性差。 |
本地测试或单机开发环境 |
MySQL |
元数据存储在独立 MySQL 实例; 支持多用户并发访问 ,稳定性高,需额外维护数据库。 |
生产环境或多团队协作场景 |
远程元存储 |
使用 Thrift 服务(如 Hive Metastore Server)集中管理元数据, 解耦计算与元数据服务 。 |
大规模集群或与 Spark 等工具集成 |
选择建议:
- 开发测试:内嵌 Derby 简单易用,但需避免多客户端同时操作。
- 生产环境:优先选择 MySQL 或远程元存储,确保高可用性和并发性。
比如在一个表中 u_id 数量特别大时,可能会导致数据倾斜,应该怎样防止数据倾斜?
当 u_id
分布极不均匀时,数据倾斜通常发生在 Join 或 Group By 操作中,解决方案需结合业务逻辑与计算框架特性:
1. 预处理倾斜 Key
- 过滤无效值:若
u_id
包含大量空值(NULL),先过滤或填充随机值。 - 分离热点数据:将高频
u_id
单独提取处理,再与其他数据合并结果。
2. SQL 逻辑优化
- Map Join:若倾斜表为小表,可强制广播到所有 Map 任务,避免 Shuffle。
- 随机打散 Key:对倾斜 Key 添加随机前缀,分散数据到不同 Reduce 任务。
3. 参数调优
- 开启负载均衡:
hive.groupby.skewindata=true
自动对 Group By 做两阶段聚合。 - 增加 Reduce 数量:通过
set mapred.reduce.tasks=1000
分散处理压力。
4. 分桶表优化
- 对
u_id
分桶(Clustered By),将数据均匀分布到多个文件,减少单个 Reduce 负载。
核心思路:分散热点数据或避免 Shuffle 阶段的集中处理,结合业务需求选择最合适的方案。
Hive 的窗口函数有哪些?请分别说明它们的使用场景和作用,并举例说明。
Hive 的窗口函数(Window Functions)用于在特定数据窗口内执行计算,支持复杂的分组和排序操作。以下是常见窗口函数及其典型应用场景:
1. 排名函数
- ROW_NUMBER():为每一行分配唯一的连续序号,即使值相同也会区分。 场景:生成唯一排名,如用户行为日志按时间排序后标记顺序。
- RANK() 与 DENSE_RANK():按值排序后分配排名,但处理重复值的方式不同。 RANK():相同值共享排名,后续序号跳跃(如 1,1,3)。DENSE_RANK():相同值共享排名,后续序号连续(如 1,1,2)。场景:成绩排名中处理并列名次。
2. 聚合类窗口函数
- SUM()/AVG()/COUNT() OVER():在窗口内累加、平均或计数。 场景:计算累计销售额或移动平均。
3. 偏移函数
- LAG() 与 LEAD():访问当前行之前或之后的指定偏移量数据。 场景:分析用户连续登录天数或环比增长。
4. 分布函数
- NTILE(n):将数据分为
n
个近似相等的桶。 场景:将用户按消费金额分为高、中、低三组。
关键点:窗口函数通过 PARTITION BY
定义分组,ORDER BY
控制排序,ROWS/RANGE
指定窗口范围,灵活支持复杂分析需求。
在使用 Hive 时,数据会同步到 HDFS,针对小文件问题通常有哪些解决方法?
小文件问题指 HDFS 中存在大量小于块大小(如 128MB)的文件,导致元数据压力增大和计算效率降低。常见解决方案如下:
1. 合并已有小文件
- 输出阶段合并:通过 Hive 参数在任务结束时自动合并。
- 定期执行合并脚本:使用
ALTER TABLE table CONCATENATE
合并小文件(仅适用于 RCFile 或 ORC 格式)。
2. 写入时避免生成小文件
- 减少 Reduce 数量:合理设置
mapred.reduce.tasks
,避免过多的 Reduce 任务产生小文件。 - 使用动态分区优化:通过
hive.exec.dynamic.partition.mode=nonstrict
避免动态分区过多导致小文件。
3. 外部工具处理
- Hadoop Archive (HAR):将小文件打包为归档文件,减少 NameNode 负载,但读取时需额外解压。
- 使用 Spark 或 DistCP:通过其他计算框架预处理数据后再导入 Hive。
4. 存储格式优化
- 采用列式存储格式(如 ORC、Parquet),其高压缩率和块结构能减少小文件影响。
请详细描述 Hive Shuffle 的具体过程。
Shuffle 是 Hive 执行 MapReduce 任务时数据从 Map 阶段到 Reduce 阶段的传输过程,核心步骤包括:
- Map 阶段输出排序Map 任务将输出数据按 Key 进行分区(Partition),确保相同 Key 的数据进入同一 Reduce 任务。数据在 Map 端内存中按 Key 排序,并写入本地磁盘的临时文件。
- 溢写(Spill)与合并(Merge)当 Map 输出缓冲区达到阈值(mapreduce.task.io.sort.mb)时,数据会溢写到磁盘。多次溢写生成的临时文件会合并为一个已排序的大文件,减少后续传输开销。
- Fetch 阶段(数据拉取)Reduce 任务通过 HTTP 请求从各个 Map 任务的磁盘中拉取属于自己分区的数据。数据拉取后会在 Reduce 端再次排序合并,形成最终输入文件。
- 压缩优化若开启中间数据压缩(mapreduce.map.output.compress=true),Map 输出会以压缩格式传输,减少网络 IO。
性能瓶颈:Shuffle 的磁盘 IO 和网络传输是任务的主要耗时环节,合理设置分区数、压缩算法和内存参数可显著提升效率。
Hive 有哪些保存元数据的方式?这些方式各自的特点和适用场景是什么?
Hive 元数据存储方式决定了其多用户协作能力和部署复杂度,主要有以下三种:
内嵌 Derby |
默认模式,元数据存储在本地 Derby 数据库; 仅支持单会话访问 ,稳定性差。 |
本地测试或单机开发环境 |
MySQL |
元数据存储在独立 MySQL 实例; 支持多用户并发访问 ,稳定性高,需额外维护数据库。 |
生产环境或多团队协作场景 |
远程元存储 |
使用 Thrift 服务(如 Hive Metastore Server)集中管理元数据, 解耦计算与元数据服务 。 |
大规模集群或与 Spark 等工具集成 |
选择建议:
- 开发测试:内嵌 Derby 简单易用,但需避免多客户端同时操作。
- 生产环境:优先选择 MySQL 或远程元存储,确保高可用性和并发性。
比如在一个表中 u_id 数量特别大时,可能会导致数据倾斜,应该怎样防止数据倾斜?
当 u_id
分布极不均匀时,数据倾斜通常发生在 Join 或 Group By 操作中,解决方案需结合业务逻辑与计算框架特性:
1. 预处理倾斜 Key
- 过滤无效值:若
u_id
包含大量空值(NULL),先过滤或填充随机值。 - 分离热点数据:将高频
u_id
单独提取处理,再与其他数据合并结果。
2. SQL 逻辑优化
- Map Join:若倾斜表为小表,可强制广播到所有 Map 任务,避免 Shuffle。
- 随机打散 Key:对倾斜 Key 添加随机前缀,分散数据到不同 Reduce 任务。
3. 参数调优
- 开启负载均衡:
hive.groupby.skewindata=true
自动对 Group By 做两阶段聚合。 - 增加 Reduce 数量:通过
set mapred.reduce.tasks=1000
分散处理压力。
4. 分桶表优化
- 对
u_id
分桶(Clustered By),将数据均匀分布到多个文件,减少单个 Reduce 负载。
核心思路:分散热点数据或避免 Shuffle 阶段的集中处理,结合业务需求选择最合适的方案。
请详细说明 order by、sort by、cluster by、distribute by 的区别,并举例说明它们的用法。
Hive 中的排序和分发操作直接影响数据在计算过程中的分布方式,以下四类语句的核心差异在于全局排序、局部排序及数据分发规则:
- ORDER BY全局排序:对全表数据进行排序,最终输出一个文件(除非数据量极大)。缺点:数据量过大时可能因单点处理导致性能瓶颈。示例:查询销售额前 10 的用户:
- SORT BY局部排序:在 每个 Reduce 任务内部 对数据排序,但不同 Reduce 任务之间的数据不保证全局有序。适用场景:需在分布式处理中优化后续操作(如二次排序)。示例:按地区分区后,每个分区内按销售额排序:
- DISTRIBUTE BY数据分发:按指定字段将数据分发到不同 Reduce 任务,类似 MapReduce 的 Partitioner 逻辑。常与 SORT BY 联用:先分发再排序。示例:按用户 ID 分发数据,确保相同 u_id 进入同一 Reduce 任务:
- CLUSTER BY组合操作:等价于 DISTRIBUTE BY col SORT BY col,即按同一字段分发并排序。适用场景:当分发和排序字段相同时简化语法。示例:按日期分发并排序:
关键总结:
ORDER BY
全局有序但性能差,适合小数据量;SORT BY
+DISTRIBUTE BY
组合灵活,适合大数据量;CLUSTER BY
是前两者的语法糖,但字段必须相同。
你是否有用 mapreduce 完成过 hive-sql 计算?若有,请简述一下具体流程。
Hive 本质上将 SQL 转换为 MapReduce 任务执行,以下以 SELECT COUNT(*) FROM table
为例,说明其底层流程:
- 解析与编译Hive 将 SQL 语句解析为 抽象语法树(AST),并生成逻辑执行计划。
- 优化与物理计划优化器对逻辑计划进行调整(如谓词下推),最终生成 MapReduce 任务的物理计划。
- Map 阶段输入分片:每个 Mapper 处理一个 HDFS 数据块。Map 函数:逐行读取数据,输出键值对 <Key, 1>(Key 可设为常量,如 dummy_key)。
- Shuffle 阶段所有 Mapper 输出的 <dummy_key, 1> 会被 Hash 分发到同一个 Reducer。
- Reduce 阶段Reduce 函数:对相同 Key 的值求和,得到总行数。
- 输出结果Reducer 将最终结果写入 HDFS,Hive 客户端读取并返回给用户。
核心特点:
- 自动转换:用户无需手动编写 MapReduce 代码,Hive 自动完成翻译。
- 扩展性:通过自定义 Mapper/Reducer 可处理复杂逻辑,但需遵循 MapReduce 编程模型。
在两表进行 join 操作时,mapreduce 是怎样处理的?请详细描述其过程。
Hive 的 Join 操作在 MapReduce 中主要通过 Reduce 端 Join 实现(默认方式),具体流程如下:
- Map 阶段数据读取:两个表的 Mapper 分别读取数据。打标签:为每条数据添加来源表标签(如 tag=0 表 A,tag=1 表 B)。输出键值对:以 Join 字段为 Key,附加标签和完整记录为 Value。
- Shuffle 阶段按 Key 分区:相同 user_id 的数据被发送到同一 Reducer。排序:数据按 Key 排序,可优化后续合并效率。
- Reduce 阶段数据分组:Reducer 接收同一 user_id 的所有记录,按标签分为表 A 和表 B 的数据集合。笛卡尔积:遍历两个集合,输出所有匹配组合(若为 Inner Join,仅输出存在交集的结果)。
优化策略:
- Map Join:若小表可放入内存,直接在 Map 端完成 Join,避免 Shuffle。
- Bucket Join:若表已按 Join 字段分桶,可减少数据扫描量。
Hive 的 join 操作原理是什么?left join、right join、inner join、outer join 有哪些异同点?请结合实例说明。
Join 原理:Hive 通过 MapReduce 或 Tez 引擎实现表关联,核心逻辑是将相同 Join Key 的数据分发到同一计算节点进行匹配。
Join 类型对比:
INNER JOIN |
仅保留两表中 Key 匹配 的记录。 |
|
LEFT JOIN |
保留左表所有记录,右表无匹配时填充 NULL。 |
左表为用户表,右表为订单表,结果包含无订单的用户。 |
RIGHT JOIN |
保留右表所有记录,左表无匹配时填充 NULL。 |
右表为商品表,左表为库存表,结果包含无库存的商品。 |
FULL OUTER JOIN |
保留两表所有记录,无匹配时填充 NULL。 |
合并两部门员工数据,显示所有员工及跨部门协作情况。 |
关键点:
- 数据倾斜处理:若某 Key 数据量过大,需采用 Map Join 或随机打散优化。
- 执行计划差异:LEFT JOIN 和 RIGHT JOIN 可通过调整表顺序相互转换,但 FULL OUTER JOIN 需独立处理。
Hive 的三种自定义函数分别是什么?请详细说明其实现步骤与流程,以及它们之间的区别和各自的作用。
Hive 支持三类自定义函数,扩展数据处理能力:
- UDF(User-Defined Function)作用:单行数据转换,如字符串处理、类型转换。实现步骤: 继承 org.apache.hadoop.hive.ql.exec.UDF。实现 evaluate() 方法。注册使用:
- UDAF(User-Defined Aggregate Function)作用:多行数据聚合,如自定义统计指标。实现步骤: 继承 org.apache.hadoop.hive.ql.exec.UDAF。定义静态内部类实现 UDAFEvaluator,重写 init()、iterate()、terminatePartial() 等方法。示例:实现计算中位数的 UDAF。
- UDTF(User-Defined Table-Generating Function)作用:单行输入生成多行输出,如数据拆分或 JSON 解析。实现步骤: 继承 org.apache.hadoop.hive.ql.udf.generic.GenericUDTF。实现 process() 和 close() 方法,通过 forward() 输出多行。
核心区别:
- 输入输出粒度:UDF 单行到单行,UDAF 多行到单行,UDTF 单行到多行。
- 应用场景:UDF 用于字段级转换,UDAF 用于聚合统计,UDTF 用于数据扁平化。
Hive 外部表删除时会发生什么情况?与内部表删除有什么区别?
Hive 的外部表和内部表在删除时的行为差异直接体现了对数据生命周期的控制逻辑:
- 外部表删除操作:仅删除元数据:Hive 的元数据库(如 MySQL)中关于该表的定义会被清除,但实际数据文件仍保留在 HDFS 或云存储的原始路径中。适用场景:适用于数据需要被多个工具(如 Spark、Presto)共享的情况,避免因误删导致数据丢失。
- 内部表删除操作:删除元数据和数据:Hive 会彻底清除元数据,并同步删除表对应的 HDFS 数据目录。风险提示:若未提前备份,数据将无法恢复,需谨慎操作。
核心区别:
- 数据是否保留是两者最根本的差异。外部表的删除仅解除元数据关联,而内部表的删除是“彻底销毁”。
- 业务影响:外部表适合管理重要业务数据,内部表适合临时或中间结果存储。
请详细说明 Hive 的 UDF 函数开发流程。
开发 Hive UDF(用户自定义函数)的核心目标是扩展 HiveQL 的功能,例如实现复杂的数据转换或业务逻辑。以下是详细步骤:
- 编写 Java 类:继承 org.apache.hadoop.hive.ql.exec.UDF 类。实现 evaluate() 方法,定义输入输出逻辑。
- 打包与部署:将代码编译为 JAR 包,上传至 Hive 服务器或 HDFS。
- 注册 UDF:在 Hive 会话中声明函数,使其可在 SQL 中调用。
- 测试与使用:
关键注意事项:
- 输入输出类型:Hive 会自动进行类型转换,但建议在
evaluate()
方法中显式处理数据类型。 - 错误处理:需在代码中捕获异常,避免任务因 UDF 错误而失败。
Hive 为什么要用 Tez 框架?与其他框架相比,它有哪些优势?
Tez 是 Hive 的新一代执行引擎,旨在解决 MapReduce 的效率瓶颈,其优势主要体现在执行模型和资源利用率上:
执行模型 |
基于 DAG(有向无环图) ,任务间直接传递数据,减少中间落盘。 |
基于 多阶段 MapReduce ,每个阶段需写磁盘,IO 开销大。 |
资源申请 |
动态资源复用 ,容器可重复利用,减少启动开销。 |
每个任务独立申请容器,启动延迟高。 |
适用场景 |
适合复杂查询(如多表 Join、子查询嵌套)。 |
适合简单批处理任务。 |
实际效果:
- 速度提升:Tez 可将某些查询速度提升数倍,尤其对于需要多阶段处理的任务。
- 资源节省:减少磁盘 IO 和容器启动次数,降低集群负载。
Hive 如果不用参数调优,在 map 和 reduce 端应该分别做哪些操作来优化性能?
在不依赖参数调优的情况下,可通过数据预处理和计算逻辑优化提升性能:
Map 端优化:
- 减少输入数据量: 分区裁剪:利用分区表特性,提前过滤无效分区(如 WHERE dt='2023-01-01')。列式存储:使用 ORC/Parquet 格式,仅读取查询所需的列。
- 合并小文件:通过
ALTER TABLE table CONCATENATE
合并小文件,减少 Map 任务数。
Reduce 端优化:
- 避免数据倾斜: 均匀分布 Key:对高频 Key 添加随机后缀,分散数据到多个 Reduce 任务。预聚合:在 Map 端使用 Combiner 提前聚合数据,减少 Shuffle 数据量。
- 合理设置分区字段:确保
DISTRIBUTE BY
的字段分布均匀,避免 Reduce 负载不均。
通用策略:
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
17年+码农经历了很多次面试,多次作为面试官面试别人,多次大数据面试和面试别人,深知哪些面试题是会被经常问到。 在多家企业从0到1开发过离线数仓实时数仓等多个大型项目,详细介绍项目架构等企业内部秘不外传的资料,介绍踩过的坑和开发干货,分享多个拿来即用的大数据ETL工具,让小白用户快速入门并精通,指导如何入职后快速上手。 计划更新内容100篇以上,包括一些企业内部秘不外宣的干货,欢迎订阅!