Java中的配置单元UDF在创建表时失败



这两个查询之间的区别是什么:

SELECT my_fun(col_name) FROM my_table;

CREATE TABLE new_table AS SELECT my_fun(col_name) FROM my_table;

其中my_fun是一个java UDF。

我之所以这么问,是因为当我创建新表(第二个查询(时,我收到了一个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));

但问题是,为什么它在并没有创建表的情况下工作,而在创建表的时候失败?

问题可能出在读取文件的方式上。尝试将文件路径作为UDF中的第二个参数传递,然后读取如下

private BufferedReader getReaderFor(String filePath) throws HiveException {
try {
Path fullFilePath = FileSystems.getDefault().getPath(filePath);
Path fileName = fullFilePath.getFileName();
if (Files.exists(fileName)) {
return Files.newBufferedReader(fileName, Charset.defaultCharset());
}
else
if (Files.exists(fullFilePath)) {
return Files.newBufferedReader(fullFilePath, Charset.defaultCharset());
}
else {
throw new HiveException("Could not find "" + fileName + "" or "" + fullFilePath + "" in inersect_file() UDF.");
}
}
catch(IOException exception) {
throw new HiveException(exception);
}
}
private void loadFromFile(String filePath) throws HiveException {
set = new HashSet<String>();
try (BufferedReader reader = getReaderFor(filePath)) {
String line;
while((line = reader.readLine()) != null) {
set.add(line);
}
} catch (IOException e) {
throw new HiveException(e);
}
}

使用文件读取器的不同通用UDF的完整代码可以在这里找到

我认为有几点不清楚,所以这个答案是基于假设的。

首先,重要的是要理解,hive目前优化了几个简单的查询,根据您的数据大小,为您工作的查询SELECT my_fun(col_name) FROM my_table;很可能是从您执行作业的客户端本地运行的,这就是为什么您的UDF可以访问本地可用的配置文件;执行模式";是因为您的数据大小。CTAS触发一个独立于输入数据的作业,该作业在集群中分布式运行,每个工作人员都无法访问您的配置文件。

看起来您正试图从本地文件系统读取配置文件,而不是从HDSFSFiles.readAllBytes(Paths.get(configPath))读取配置文件,这意味着您的配置必须在所有工作节点中复制,或者之前添加到分布式缓存中(您可以使用add file from this,这里的doc。您可以在这里找到关于从UDF访问分布式缓存中的文件的其他问题。

另一个问题是,您正在通过一个环境变量传递配置文件的位置,该环境变量不会作为配置单元作业的一部分传播到工作节点。您应该将此配置作为配置单元配置传递,假设您正在扩展GenericUDF,则可以从UDF访问配置单元配置。

相关内容

  • 没有找到相关文章

最新更新