복붙노트

[HADOOP] PIG UDF는 다중 줄이있는 튜플을 다른 매퍼로 분할합니다.

HADOOP

PIG UDF는 다중 줄이있는 튜플을 다른 매퍼로 분할합니다.

각 튜플이 여러 줄에 걸쳐있는 파일을 가지고 있습니다. 예를 들면 다음과 같습니다.

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
.
.
.

그래서 위의 파일에는 두 개의 튜플이 있습니다. 내가 START인지 확인한 후 내 튜플을 초기화 할 getNext () 함수를 정의한 UDF를 작성했습니다. END이면 문자열 버퍼에서 튜플을 반환 할 것입니다. 그렇지 않으면 그냥 문자열 버퍼에 문자열을 추가합니다.

파일 크기가 64MB 인 HDFS 블록 크기 (Amazon EMR)보다 작 으면 좋지만 이보다 더 큰 크기에서는 실패합니다. 나는이 블로그 게시물을 찾아서 구글을 찾으려고 노력한다. Raja의 설명은 이해하기 쉽고 샘플 코드를 제공했습니다. 그러나 코드는 돼지 LoadFunc에 대해 getNext () 대신 RecordReader 부분을 구현합니다. 아무도 다중 줄기 돼지 튜플 분할 문제를 처리하는 경험이 있다면 궁금해? 내가 앞서 돼지에 RecordReader를 구현해야합니까? 그렇다면 어떻게?

감사.

해결법

  1. ==============================

    1.가이가 언급 한대로 입력을 사전 처리하거나 여기에 설명 된 다른 트릭을 적용 할 수 있습니다.

    가이가 언급 한대로 입력을 사전 처리하거나 여기에 설명 된 다른 트릭을 적용 할 수 있습니다.

    가장 깨끗한 솔루션은 하나의 레코드 / START-END를 만드는 사용자 지정 InputFormat (해당 RecordReader와 함께)을 구현하는 것입니다. Pig의 LoadFunc는 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);
        }
    }
    

    LoadFunc은 InputFormat과 RecordReader를 초기화 한 후 데이터의 입력 위치를 찾고 recordReader에서 레코드를 얻기 시작하고 입력이 완전히 읽힐 때까지 결과 튜플 (getNext ())을 생성합니다.

    커스텀 InputFormat의 몇 가지 발언 :

    RecordReader가 수정 된 버전 인 사용자 지정 InputFormat을 만듭니다. org.apache.hadoop.mapreduce.lib.input.LineRecordReader : 대부분의 메소드는 initialize ()를 제외하고는 동일하게 유지 : 사용자 정의 LineReader를 호출합니다. (org.apache.hadoop.util.LineReader에 기반 함). InputFormat의 키는 라인 오프셋 (Long)이고, 값은 커스텀 쓰기 가능. 이렇게하면 키 - 값 쌍의 목록으로 레코드 필드 (START-END 사이의 데이터)가 유지됩니다. RecordReader의 nextKeyValue ()가 호출 될 때마다 레코드가 LineReader에 의해 사용자 정의 Writable에 기록됩니다. 모든 것의 요지는 당신이 어떻게 LineReader.readLine ()를 구현합니다.

    또 다른 방법은 TextInputFormat의 구분자를 변경하는 것입니다 (Hadoop 0.23에서 구성 가능, textinputformat.record.delimiter 참조). 가능한 경우 데이터 구조에 적합한 것으로 변경하십시오. 이 경우 KV 쌍을 분할하고 추출 할 필요가있는 텍스트에서 데이터를 얻게 될 것입니다.

  2. ==============================

    2.구분 기호로 시작할 수있는 경우 UDF 없이도 코드가 작동 할 수 있습니다.

    구분 기호로 시작할 수있는 경우 UDF 없이도 코드가 작동 할 수 있습니다.

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

    결과는 다음과 같습니다.

        (
        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
        )
    

    이제 둘 다 두 개의 튜플로 분리됩니다.

  3. from https://stackoverflow.com/questions/13871134/pig-udf-handle-multi-lined-tuple-split-into-different-mapper by cc-by-sa and MIT license