有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

SELECT my_fun(col_name) FROM my_table;

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

我的乐趣是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));

但问题是为什么它在未创建表时工作,而在创建表时失败


共 (2) 个答案

  1. # 1 楼答案

    问题可能在于您读取文件的方式。尝试将文件路径作为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的完整代码可以在here

  2. # 2 楼答案

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

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

    看起来您试图从本地文件系统而不是从HDSFS Files.readAllBytes(Paths.get(configPath))读取配置文件,这意味着您的配置必须在所有工作节点中复制,或者之前添加到分布式缓存中(您可以使用本文档中的添加文件,dochere)。关于从UDF访问分布式缓存中的文件,您可以找到另一个问题here

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