如何在 hive udf 中访问配置数据-踩坑记录,方案汇总与对比-udf中可以写sql吗?

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 如何在 hive udf 中访问配置数据-踩坑记录,方案汇总与对比-udf中可以写sql吗?

近日我司有个大数据业务系统在某客户现场实时部署时,遇到了一个Hive udf的使用问题,这个问题比较难排查,因为涉及到对Hive的架构原理以及hive sql 解析优化和执行的细节的理解。在此跟大家分享总结下,希望对大家以后使用hive sql 尤其是udf 的编写能有所帮助。

一。问题现象

该客户使用的是 cdh6.2,对 hive 开启了 kerberos 安全认证也使用了sentry插件来进行 hive 表的权限管理,出于安全考量他们禁止在 udf 中直接访问hive 底层 hdfs 上的数据,所以我们的大数据业务系统将要获取的配置信息,即“交易日数据“定义为了 hive 表,然后在 udf 代码中通过建立到 hiveserver2 的 jdbc 连接然后执行 Statement.executeQuery("select close_date from ods_closedate") 的方式来获取交易日数据。

在测试时,通过 beeline 连接到 hiveserver2 然后通过 select hiveudf.lastexchangeday(20200102) 调用 udf 获取上一个交易日,但是实际执行时发现以上 udf 调用并不能成功获取到上一个交易日 20200101,观察发现客户端卡死且没有任何报错信息也没有结果,同时留意到链接同一个 hiveserver2实例的其它客户端能够正常连接到 hiveserver2 也能提交 sql,但是提交的sql 即使是最简单的 “show databases” ,客户端也是处于长时间卡死的状态且没有任何报错信息也没有任何结果。只有重启后 hiveserver2 才能正常对外提供服务。

二。问题原因

首先大家要理解下 Hive 的架构原理和 sql 执行细节:用户通过客户端 (可以是beeline, 也可以是java程序)建立到 hiveserver2 的 jdbc 连接,然后提交hive sql 给 hiveserver2,hiveserver2 收到 sql 后需要做解析编译和优化以生成最终的 mr/tez/spark 任务 (解析编译和优化需要访问 hive metastore service 以获得表和 udf 等的元数据信息),这些 mr/tez/spark 任务在执行时首先需要到 yarn 上申请资源,然后在申请获得的 yarn container 中执行这些任务并将结果返回给 hiveserver2 进而返回给客户端。这些 Sql 包括 sql中的 Udf,其解析编译优化和生成 mr/tez/spark 任务是在 hiveserver2 中进行的,但并不是所有的 sql 和 udf 都会生成 mr/tez/spark 任务,比如 select current_timestamp() 就不会生成 mr/tez/spark 任务,也不需要向 yarn 申请资源获得 container 容器,而是直接在 hiveserver2 中执行的。

该业务系统通过 beeline 客户端连接到 hiveserver2 实例后,通过语句 “select lastexchangeday(20200102)” 调用 Udf 查询交易日数据,该 udf 在hiveserver2 的解析编译和优化过程中也不会生成任何 mr/tez/spark 任务 (因为 hiveserver2 在对语句 “select hiveudf.lastexchangeday(20200102)”进行解析编译优化时通过语法检查发现该 sql 语句并不包含任何 hive 表,所以 hiveserver2 认为不需要生成 mr/tez/spark 任务分布式地执行),所以该 udf 的最终执行也是在 hiveserver2 中执行的,此时由于该 udf 代码本身包含了建立到 hiveserver2 的jdbc连接和执行Statement.executeQuery("select close_date from hs_ods_closedate"),所以其执行过程,就相当于在 hiveserver2 这个 jvm 中建立到同一个hiveserver2 的 Jdbc 连接并提交执行 sql "select close_date from hs_ods_closedate",也就是 hiveserver2 这个 jvm 即是 sql 调用的客户端也是 sql 执行的服务端。在当前的 hiveserver2 实现中,这种调用方式就会引起 hiveserver2 无法响应其它客户端的sql (虽然其它客户端还可以成功连接到该 hiveserver2),也无法完成当前 udf 底层的 sql 调用。

更细节的信息,大家可以参考源码,也可以观察调用时 hiveserver2 的堆栈信息。


三。问题解决方案

其实总结下来,udf中读取配置参数,主要有四种方式:

  • 方案1. 使用一个hdfs文件存储配置参数,该hdfs配置文件一般用csv/json/xml等半结构化格式;udf通过直接读取hdfs文件获取配置参数;用户需要更改配置参数时直接更改本地文件并上传覆盖hdfs上的配置文件;
  • 方案2. 使用一个本地文件存储配置参数,该本地配置文件一般用csv/json/xml/properties等文本格式,且打包到udf对应的jar包中;udf通过读取jar包内嵌的配置文件获取配置参数;用户需要更改配置参数时需要更改本地文件并替换jar包中的配置文件;
  • 方案3. 使用一个hive表存储配置参数,且该表最好是外表且以csv/tsv等文本格式存储;udf通过直接读取该表底层的hdfs文件获得配置参数;用户需要更改配置参数时可以直接使用hive sql dml语句;
  • 方案4. 使用一个hive表存储配置参数; udf在内部代码中通过sql读取该配置参数表获得配置参数;用户需要更改配置参数时可以直接使用hive sql dml语句;==> 以上发生问题的业务系统,我们采用的就是该方案4!该方案的细节和注意项,请继续向下阅读

以上四种方式各有利弊,也都有客户线上采用,具体选用哪个,无非是在配置文件内容更改的便捷性, udf升级运维的便捷性,udf的执行效率,还有客户安全规范,这几个考量点之间的权衡。

不过有一点需要指出,sentry是基于插件机制对hive库和表直接进行的权限管理,如果直接访问库和表底层的hdfs文件就绕过了sentry的安全管理,所以一般使用sentry时确实不建议直接访问hdfs文件,但这也不是绝对的,因为不使用sentry安全机制并不代表就是不安全的,我们完全可以合理使用hdfs对目录和文件的权限管控机制来达到安全的目的,此时可以直接使用hdfs文件或合理使用hive外表,由客户指定hdfs文件或hive外表的具体路径和权限,然后udf执行时通过配置参数获取hdfs文件或hive外表对应的hdfs文件的路径,并直接读取获取配置内容。


四。方案四易踩坑细节分析

其实业界普遍不建议在 hive udf 内部代码中调用 hive sql,因为稍有不慎就可能会出现如上问题现象中描述的 hiveserver2 不响应的情况。但该方式也并非完全行不通,只是在使用上有各种小细节要注意,而且跟不同版本hiveserver2 的解析编译和优化相关代码的具体实现有关:

  • 如果 beeline 或用户 java 程序连接的是 hiveserver2 实例1,而udf内部代码提交的sql是提交到 hiveserver2 实例2, 则不会出现上述问题;
  • 由于hive 老客户端 hive/hive service –cli 在功能上包含了 hive 新客户端 beeline 和 hiveserver2 的功能,所以通过老客户端 hive 提交 udf,而 udf 内部代码中提交 sql 到 hiveserver2 实例上,也是没问题的;
  • 如果用户提交的 udf 在经过 hiveserver2 的解析编译和优化后会生成mr/tez/spark 任务,此时由于 mr/tez/spark 任务是在向 yarn 申请获得的 container 中执行的,所以 udf 内部代码中的 sql 是从 yarn container 中反向提交给 hiveserver2 去执行的,也不会存在上述问题。
  • 但由于 hiveserver2 何时经解析编译和优化会生成 mr/tez/spark 任务,何时不会生成 mr/tez/spark 任务,跟 hiveserver2 不同版本的具体实现有关,也跟我们 udf 的调用方式有关,不好一概而论,所以我们一般不推荐使用这种方式。
  • 经验证,select lastexchangeday(20200102) 不会生成mr/tez/spark任务,select lastexchangeday(current_date) from userTableA 会生成 mr/tez/spark 任务,也即当 udf 参数是常量时不会生成 mr/tez/spark 任务,当 udf 参数是从其他 hive 表中查询获得时是会生成mr/tez/spark 任务的。(在cdh6.2中验证是这样,其他版本差异较大的不一定)。
相关文章
|
2天前
|
SQL 容灾 关系型数据库
阿里云DTS踩坑经验分享系列|DTS打通SQL Server数据通道能力介绍
SQL Server 以其卓越的易用性和丰富的软件生态系统,在数据库行业中占据了显著的市场份额。作为一款商业数据库,外部厂商在通过解析原生日志实现增量数据捕获上面临很大的挑战,DTS 在 SQL Sever 数据通道上深研多年,提供了多种模式以实现 SQL Server 增量数据捕获。用户可以通过 DTS 数据传输服务,一键打破自建 SQL Server、RDS SQL Server、Azure、AWS等他云 SQL Server 数据孤岛,实现 SQL Server 数据源的流动。
37 0
阿里云DTS踩坑经验分享系列|DTS打通SQL Server数据通道能力介绍
|
9天前
|
SQL 关系型数据库 MySQL
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
21 2
|
2月前
|
SQL Oracle 关系型数据库
如何在 Oracle 中配置和使用 SQL Profiles 来优化查询性能?
在 Oracle 数据库中,SQL Profiles 是优化查询性能的工具,通过提供额外统计信息帮助生成更有效的执行计划。配置和使用步骤包括:1. 启用自动 SQL 调优;2. 手动创建 SQL Profile,涉及收集、执行调优任务、查看报告及应用建议;3. 验证效果;4. 使用 `DBA_SQL_PROFILES` 视图管理 Profile。
|
4月前
|
SQL 存储 缓存
SQL Server 数据太多如何优化
11种优化方案供你参考,优化 SQL Server 数据库性能得从多个方面着手,包括硬件配置、数据库结构、查询优化、索引管理、分区分表、并行处理等。通过合理的索引、查询优化、数据分区等技术,可以在数据量增大时保持较好的性能。同时,定期进行数据库维护和清理,保证数据库高效运行。
120 4
|
5月前
|
SQL 移动开发 Oracle
SQL语句实现查询连续六天数据的方法与技巧
在数据库查询中,有时需要筛选出符合特定时间连续性条件的数据记录
|
5月前
|
SQL 存储 关系型数据库
添加数据到数据库的SQL语句详解与实践技巧
在数据库管理中,添加数据是一个基本操作,它涉及到向表中插入新的记录
|
10月前
|
SQL 数据采集 数据挖掘
大数据行业应用之Hive数据分析航班线路相关的各项指标
大数据行业应用之Hive数据分析航班线路相关的各项指标
238 1
|
10月前
|
SQL 分布式计算 数据库
【大数据技术Spark】Spark SQL操作Dataframe、读写MySQL、Hive数据库实战(附源码)
【大数据技术Spark】Spark SQL操作Dataframe、读写MySQL、Hive数据库实战(附源码)
372 0
|
5月前
|
SQL 分布式计算 Java
大数据-96 Spark 集群 SparkSQL Scala编写SQL操作SparkSQL的数据源:JSON、CSV、JDBC、Hive
大数据-96 Spark 集群 SparkSQL Scala编写SQL操作SparkSQL的数据源:JSON、CSV、JDBC、Hive
126 0
|
8月前
|
SQL 分布式计算 大数据
大数据处理平台Hive详解
【7月更文挑战第15天】Hive作为基于Hadoop的数据仓库工具,在大数据处理和分析领域发挥着重要作用。通过提供类SQL的查询语言,Hive降低了数据处理的门槛,使得具有SQL背景的开发者可以轻松地处理大规模数据。然而,Hive也存在查询延迟高、表达能力有限等缺点,需要在实际应用中根据具体场景和需求进行选择和优化。

热门文章

最新文章