Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hadoop PIG UDF将多行元组拆分为不同的映射器_Hadoop_Amazon Web Services_Mapreduce_User Defined Functions_Apache Pig - Fatal编程技术网

Hadoop PIG UDF将多行元组拆分为不同的映射器

Hadoop PIG UDF将多行元组拆分为不同的映射器,hadoop,amazon-web-services,mapreduce,user-defined-functions,apache-pig,Hadoop,Amazon Web Services,Mapreduce,User Defined Functions,Apache Pig,我有一个文件,其中每个元组跨越多行,例如: START name: Jim phone: 2128789283 address: 56 2nd street, New York, USA END START name: Tom phone: 6308789283 address: 56 5th street, Chicago, 13611, USA END . . . 上面是我文件中的两个元组。我编写了我的UDF,它定义了一个getNext()函数,检查它是否启动,然后我将初始化我的元组;如果

我有一个文件,其中每个元组跨越多行,例如:

START
name: Jim
phone: 2128789283
address: 56 2nd street, New York, USA
END
START
name: Tom
phone: 6308789283
address: 56 5th street, Chicago, 13611, USA
END
.
.
.
上面是我文件中的两个元组。我编写了我的UDF,它定义了一个
getNext()
函数,检查它是否启动,然后我将初始化我的元组;如果是END,那么我将返回元组(从字符串缓冲区);否则,我将只将字符串添加到字符串缓冲区

如果文件大小小于HDFS块大小(在AmazonEMR上为64MB),那么它工作得很好,但是如果文件大小大于64MB,那么它将失败。我试着四处搜索,找到这个。Raja的解释很容易理解,他提供了一个示例代码。但是代码实现了
RecordReader
部分,而不是pig
LoadFunc
getNext()
。只是想知道是否有人有处理多行猪元组分裂问题的经验?我是否应该继续在Pig中实现
RecordReader
?如果是,怎么做


谢谢。

您可以像Guy提到的那样预处理您的输入,也可以应用所描述的其他技巧

我认为最干净的解决方案是实现一个定制(连同它的RecordReader)来创建一个记录/开始端。Pig位于Hadoop的InputFormat之上,因此您可以定义LoadFunc将使用的InputFormat
自定义LoadFunc的原始骨架实现如下所示:

import java.io.IOException;
import org.apache.hadoop.mapreduce.InputFormat;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.pig.LoadFunc;
import org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigSplit;
import org.apache.pig.data.Tuple;
import org.apache.pig.data.TupleFactory;

public class CustomLoader extends LoadFunc {

    private RecordReader reader;
    private TupleFactory tupleFactory;

    public CustomLoader() {
        tupleFactory = TupleFactory.getInstance();
    }

    @Override
    public InputFormat getInputFormat() throws IOException {
        return new MyInputFormat(); //custom InputFormat
    }

    @Override
    public Tuple getNext() {
        Tuple result = null;
        try {
            if (!reader.nextKeyValue()) {
                return null;
            }
            //value can be a custom Writable containing your name/value 
            //field pairs for a given record
            Object value = reader.getCurrentValue();
            result = tupleFactory.newTuple();
            // ...
            //append fields to tuple
        }
        catch (Exception e) {
            // ...
        }
        return result;
    }

    @Override
    public void prepareToRead(RecordReader reader, PigSplit pigSplit) 
      throws IOException {
        this.reader = reader;
    }

    @Override
    public void setLocation(String location, Job job) throws IOException {
        FileInputFormat.setInputPaths(job, location);
    }
}
    (
    name: Jim
    enter code here`phone: 2128789283
    address: 56 2nd street, New York, USA
    END
    )

    (
    name: Tom
    phone: 6308789283
    address: 56 5th street, Chicago, 13611, USA
    END
    )
LoadFunc
初始化
InputFormat
及其
RecordReader
后,它会找到数据的输入位置,并开始从RecordReader获取记录,创建结果元组(getNext()),直到完全读取输入

关于自定义InputFormat的一些备注:

我将创建一个自定义InputFormat,其中RecordReader是的修改版本
org.apache.hadoop.mapreduce.lib.input.LineRecordReader
:大多数方法 保持不变,除了
initialize()
:它将调用自定义LineReader (基于
org.apache.hadoop.util.LineReader
)。 InputFormat的键是行偏移量(长),值是自定义的 可写的。这将保存记录的字段(即开始和结束之间的数据)作为键值对列表。每次调用RecordReader的
nextKeyValue()
时,记录都会写入可由LineReader写入的自定义文件。整件事的要点是你是怎么做的 实现
LineReader.readLine()

另一种可能更简单的方法是更改TextInputFormat的分隔符(它在Hadoop 0.23中是可配置的,请参见
TextInputFormat.record.delimiter

适用于您的数据结构(如果可能的话)。在这种情况下,您将以
文本中的数据结束,您需要从中拆分和提取KV对并将其转换为元组。

如果您可以使用start作为分隔符,那么下面的代码可能在没有UDF的情况下工作

SET textinputformat.record.delimiter 'START';
a  =  load  '<input path>' as  (data:chararray);
dump a;

现在两者都被分成两个元组。

预处理文件会更简单,将记录的所有信息放在一行中-一行awkI无法控制输入文件如果我自己预处理,那么开销将克服Hadoop提供的好处。除了我在Hadoop中使用预处理。现在,我仍然在寻找跨映射器边界处理元组的解决方案。只是想知道您是否可以提供定制InpurFormat和RecordReader的框架实现?特别是如何处理跨越映射者边界的元组?谢谢。MyInputFormat似乎无法使用。我把print语句放在MyInputFormat的旁边,但它没有被打印出来。