在UDF中加载文件

时间:2015-11-16 11:59:10

标签: hadoop apache-pig

我需要根据UDF的评估填充字段。 UDF的输入将是输入中的一些其他字段以及csv表。目前,我采取的方法是加载CSV文件,将其分组ALL,然后将其作为包传递给UDF以及其他必需参数。然而,它需要很长时间来完成170k记录的源数据以及大约150k的csv记录的过程(大约3小时)。

我确信必须有更好的有效方法来处理这个问题,因此需要你的投入。

source_alias = LOAD 'src.csv' USING 
                            PigStorage(',') AS (f1:chararray,f2:chararray,f3:chararray);

csv_alias = LOAD 'csv_file.csv' USING 
                            PigStorage(',') AS (c1:chararray,c2:chararray,c3:chararray);

grpd_csv_alias = GROUP csv_alias ALL;

final_alias = FOREACH source_alias GENERATE f1 AS f1,
myUDF(grpd_csv_alias, f2) AS derived_f2;

这是我的UDF的高级别。

public class myUDF extends EvalFunc<String> {

    public String exec(Tuple input) throws IOException {

        String f2Response = "N";
        DataBag csvAliasBag = (DataBag)input.get(0);
        String f2 = (String) input.get(1);

        try {

                Iterator<Tuple> bagIterator = csvAliasBag.iterator();


                while (bagIterator.hasNext()) {
                    Tuple localTuple = (Tuple)bagIterator.next();
                    String col1 = ((String)localTuple.get(1)).trim().toLowerCase();
                    String col2 = ((String)localTuple.get(2)).trim().toLowerCase();
                    String col3 = ((String)localTuple.get(3)).trim().toLowerCase();
                    String col4 = ((String)localTuple.get(4)).trim().toLowerCase();

                    <Custom logic to populate f2Response based on the value in f2 and as well as col1, col2, col3 and col4>

                }
            }

            return f2Response;
        }
        catch(Exception e){
            throw new IOException("Caught exception processing input row ", e);
        }


    }

}

我认为该过程花费的时间太长,因为为源文件中的每一行构建并将csv_alias传递给UDF。

有没有更好的方法来解决这个问题?

由于

1 个答案:

答案 0 :(得分:2)

对于小文件,您可以将它们放在分布式缓存上。这会将文件作为本地文件复制到每个任务节点,然后您自己加载它。以下是Pig docs UDF section的示例。但是,我不建议每次解析文件。将结果存储在类变量中,并检查它是否已初始化。如果csv位于本地文件系统上,请使用getShipFiles。如果您使用的csv在HDFS上,则使用getCachedFiles方法。请注意,对于HDFS,文件路径后跟#和一些文本。 #左侧是HDFS路径,右侧是您希望在将其复制到本地文件系统时调用的名称。

public class Udfcachetest extends EvalFunc<String> { 

public String exec(Tuple input) throws IOException { 
    String concatResult = "";
    FileReader fr = new FileReader("./smallfile1"); 
    BufferedReader d = new BufferedReader(fr);
    concatResult +=d.readLine();
    fr = new FileReader("./smallfile2");
    d = new BufferedReader(fr);
    concatResult +=d.readLine();
    return concatResult;
} 

public List<String> getCacheFiles() { 
    List<String> list = new ArrayList<String>(1); 
    list.add("/user/pig/tests/data/small#smallfile1");  // This is hdfs file
    return list; 
} 

public List<String> getShipFiles() {
    List<String> list = new ArrayList<String>(1);
    list.add("/home/hadoop/pig/smallfile2");  // This local file
    return list;
}
}