webentwicklung-frage-antwort-db.com.de

Vorteile der Verwendung von NullWritable in Hadoop

Welche Vorteile bietet die Verwendung von NullWritable für null-Schlüssel/-Werte gegenüber der Verwendung von null-Texten (d. H. new Text(null))? Ich sehe Folgendes aus dem Buch «Hadoop: The Definitive Guide».

NullWritable ist ein spezieller Typ von Writable, da die Serialisierung null ist. Es werden keine Bytes in den Stream geschrieben oder daraus gelesen. Es wird als Platzhalter verwendet. In MapReduce kann beispielsweise ein Schlüssel oder ein Wert als NullWritable deklariert werden, wenn Sie diese Position nicht benötigen. In diesem Fall wird ein konstanter leerer Wert gespeichert. NullWritable kann auch als Schlüssel in SequenceFile nützlich sein, wenn Sie im Gegensatz zu Schlüssel-Wert-Paaren eine Liste von Werten speichern möchten. Es ist ein unveränderlicher Singleton: Die Instanz kann durch Aufrufen von NullWritable.get() abgerufen werden.

Ich verstehe nicht genau, wie die Ausgabe mit NullWritable geschrieben wird. Befindet sich in der Anfangsausgabedatei eine einzige Konstante, die angibt, dass die Schlüssel oder Werte dieser Datei null sind, sodass das MapReduce-Framework das Lesen der null-Schlüssel/-Werte ignorieren kann (je nachdem, welcher Wert null ist)? Wie werden null-Texte tatsächlich serialisiert?

Vielen Dank,

Venkat

27
Venk K

Die Schlüssel-/Werttypen müssen zur Laufzeit angegeben werden, sodass jedes Schreiben oder Lesen von NullWritables im Voraus weiß, dass es sich um diesen Typ handelt. Es gibt keine Markierung oder irgendetwas in der Datei. Und technisch gesehen sind die NullWritables "gelesen", es ist nur so, dass das "Lesen" einer NullWritable tatsächlich ein No-Op ist. Sie können selbst sehen, dass nichts geschrieben oder gelesen wird:

NullWritable nw = NullWritable.get();
ByteArrayOutputStream out = new ByteArrayOutputStream();
nw.write(new DataOutputStream(out));
System.out.println(Arrays.toString(out.toByteArray())); // prints "[]"

ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]);
nw.readFields(new DataInputStream(in)); // works just fine

Und was Ihre Frage zu new Text(null) betrifft, können Sie es auch einmal ausprobieren:

Text text = new Text((String)null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
text.write(new DataOutputStream(out)); // throws NullPointerException
System.out.println(Arrays.toString(out.toByteArray()));

Text funktioniert mit einer nullString überhaupt nicht.

22
Joe K

Sie können Ihre Zeichenfolge immer in Ihre eigene Writable-Klasse einschließen und einen booleschen Wert angeben, der angibt, dass sie leere Zeichenfolgen enthält oder nicht:

@Override
public void readFields(DataInput in) throws IOException { 
    ...
    boolean hasWord = in.readBoolean();
    if( hasWord ) {
        Word = in.readUTF();
    }
    ...
}

und

@Override
public void write(DataOutput out) throws IOException {
    ...
    boolean hasWord = StringUtils.isNotBlank(Word);
    out.writeBoolean(hasWord);
    if(hasWord) {
        out.writeUTF(Word);
    }
    ...
}
0
Arthur B

Ich ändere die Laufmethode. und erfolg

@Override
public int run(String[] strings) throws Exception {
    Configuration config = HBaseConfiguration.create();  
    //set job name
    Job job = new Job(config, "Import from file ");
    job.setJarByClass(LogRun.class);
    //set map class
    job.setMapperClass(LogMapper.class);

    //set output format and output table name
    //job.setOutputFormatClass(TableOutputFormat.class);
    //job.getConfiguration().set(TableOutputFormat.OUTPUT_TABLE, "crm_data");
    //job.setOutputKeyClass(ImmutableBytesWritable.class);
    //job.setOutputValueClass(Put.class);

    TableMapReduceUtil.initTableReducerJob("crm_data", null, job);
    job.setNumReduceTasks(0);
    TableMapReduceUtil.addDependencyJars(job);

    FileInputFormat.addInputPath(job, new Path(strings[0]));

    int ret = job.waitForCompletion(true) ? 0 : 1;
    return ret;
}
0
zwj0571