Преимущества использования NullWritable в Hadoop
В чем преимущества использования NullWritable
для null
ключей/значений с использованием текстов null
(т.е. new Text(null)
). Я вижу следующее из книги "Hadoop: The Definitive Guide".
NullWritable
является специальным типом Writable
, так как он имеет сериализацию нулевой длины. Нет байтов записываются в поток или считываются с него. Он используется в качестве заполнителя; например, в MapReduce, ключ или значение можно объявить как NullWritable
, когда вам не нужно для использования этой позиции - она эффективно сохраняет постоянное пустое значение. NullWritable также может быть полезным в качестве ключа в SequenceFile
, если вы хотите сохранить список значений, в противоположность для пар ключ-значение. Это неизменный синглтон: экземпляр можно получить, вызвав NullWritable.get()
Я не понимаю, как выписывается вывод с помощью NullWritable
? Будет ли в исходном выходном файле одно постоянное значение, указывающее, что ключи или значения этого файла null
, так что среда MapReduce может игнорировать чтение ключей/значений null
(в зависимости от того, что null
)? Кроме того, как на самом деле тексты null
сериализованы?
Спасибо,
Венкат
Ответы
Ответ 1
Типы ключей/значений должны указываться во время выполнения, поэтому все записи или чтение NullWritables
будут знать заранее, что он будет иметь дело с этим типом; в файле нет маркера или чего-либо еще. И технически NullWritables
"читаются", просто "чтение" NullWritable
на самом деле не-op. Вы сами можете убедиться, что ничего не написано или прочитано:
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
И что касается вашего вопроса о new Text(null)
, повторите попытку:
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
не будет работать вообще с null
String
.
Ответ 2
Я изменяю метод запуска. и успех
@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;
}
Ответ 3
Вы всегда можете обернуть свою строку в свой собственный класс Writable и иметь логическое значение, указывающее, что она имеет пустые строки или нет:
@Override
public void readFields(DataInput in) throws IOException {
...
boolean hasWord = in.readBoolean();
if( hasWord ) {
word = in.readUTF();
}
...
}
и
@Override
public void write(DataOutput out) throws IOException {
...
boolean hasWord = StringUtils.isNotBlank(word);
out.writeBoolean(hasWord);
if(hasWord) {
out.writeUTF(word);
}
...
}