web-dev-qa-db-fra.com

Avantages de l'utilisation de NullWritable dans Hadoop

Quels sont les avantages de l’utilisation de NullWritable pour les clés/valeurs null par rapport à l’utilisation de textes null (c.-à-d. new Text(null)). Je vois ce qui suit dans le livre «Hadoop: Le guide définitif».

NullWritable est un type spécial de Writable, car il a une sérialisation de longueur nulle. Aucun octet n'est écrit ou lu dans le flux. Il est utilisé comme espace réservé. Par exemple, dans MapReduce, une clé ou une valeur peut être déclarée en tant que NullWritable lorsque vous n’avez pas besoin d’utiliser cette position; elle stocke en réalité une valeur vide constante. NullWritable peut également être utile en tant que clé dans SequenceFile lorsque vous souhaitez stocker une liste de valeurs, par opposition à des paires clé-valeur. C'est un singleton immuable: l'instance peut être récupérée en appelant NullWritable.get()

Je ne comprends pas clairement comment le résultat est écrit avec NullWritable? Y aura-t-il une seule valeur constante dans le fichier de sortie de début indiquant que les clés ou les valeurs de ce fichier sont null, de sorte que le cadre MapReduce puisse ignorer la lecture des clés/valeurs null (selon la valeur null)? De plus, comment les textes null sont-ils sérialisés?

Merci,

Venkat

27
Venk K

Les types clé/valeur doivent être spécifiés au moment de l'exécution. Ainsi, toute écriture ou lecture de NullWritables saura à l'avance qu'il traitera avec ce type; il n'y a pas de marqueur ou quoi que ce soit dans le fichier. Et techniquement, les NullWritables sont "lus", c’est juste que "lire" un NullWritable est en réalité un no-op. Vous pouvez voir par vous-même qu'il n'y a rien du tout écrit ou lu:

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

Et pour ce qui est de votre question sur new Text(null), encore une fois, vous pouvez l'essayer:

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 ne fonctionnera pas du tout avec un nullString.

22
Joe K

Vous pouvez toujours envelopper votre chaîne dans votre propre classe Writable et avoir un booléen indiquant qu'il a des chaînes vides ou non:

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

et

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

Je change la méthode d'exécution. et le succès

@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