簡體   English   中英

Java 中的 Hive UDF 在創建表時失敗

[英]Hive UDF in Java fails when creating a table

這兩個查詢有什么區別:

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 觸發一個獨立於輸入數據的作業,該作業分布在集群中運行,每個工作人員無法訪問您的配置文件。

看起來您正在嘗試從本地文件系統讀取配置文件,而不是從 HDSFS Files.readAllBytes(Paths.get(configPath)) ,這意味着您的配置必須在所有工作節點中復制或之前添加到分布式緩存中(您可以使用 add file from this, doc here 。您可以在此處找到有關從 UDF 訪問分布式緩存中的文件的其他問題。

另一個問題是您通過環境變量傳遞配置文件的位置,該環境變量不會作為 hive 作業的一部分傳播到工作節點。 您應該將此配置作為 hive 配置傳遞,假設您正在擴展 GenericUDF, 這里有一個從 UDF 訪問 Hive 配置的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM