这两个查询之间的区别是什么:
SELECT my_fun(col_name) FROM my_table;
和
CREATE TABLE new_table AS SELECT my_fun(col_name) FROM my_table;
我的乐趣是java自定义项。
我这样问是因为当我创建新表(第二个查询)时,我收到一个java错误。
Failure while running task:java.lang.RuntimeException: java.lang.RuntimeException: Map operator initialization failed
...
Caused by: org.apache.hadoop.hive.ql.exec.UDFArgumentException: Unable to instantiate UDF implementation class com.company_name.examples.ExampleUDF: java.lang.NullPointerException
我发现错误的来源是我的java文件中的第行:
encoded = Files.readAllBytes(Paths.get(configPath));
但问题是,为什么它在未创建表时工作,而在创建表时失败?
2条答案
按热度按时间ux6nzvsh1#
问题可能出在读取文件的方式上。尝试将文件路径作为udf中的第二个参数传递,然后如下所示
这里可以找到使用文件读取器的不同通用udf的完整代码
xu3bshqb2#
我认为有几点不清楚,所以这个答案是基于假设的。
首先,重要的是要了解hive当前优化了几个简单的查询,并根据数据的大小优化了适合您的查询
SELECT my_fun(col_name) FROM my_table;
很可能是从执行作业的客户端本地运行的,这就是为什么udf可以访问本地可用的配置文件,这种“执行模式”是因为数据的大小。cta触发一个独立于输入数据的作业,该作业在集群中分布式运行,每个工作进程都无法访问您的配置文件。看起来您正在尝试从本地文件系统而不是hdsfs读取配置文件
Files.readAllBytes(Paths.get(configPath))
,这意味着您的配置必须在所有工作节点中复制,或者之前添加到分布式缓存(您可以使用add file from this,doc here)。您可以在这里找到关于从udf访问分布式缓存中的文件的另一个问题。另一个问题是,您正在通过一个环境变量传递配置文件的位置,该环境变量没有作为配置单元作业的一部分传播到工作节点。您应该将此配置作为配置单元配置传递,这里有一个从udf访问配置单元配置的答案,假设您正在扩展genericudf。