Объединить выходные файлы после фазы уменьшения

В mapreduce каждая задача сокращения записывает свой вывод в файл с именем part-r-nnnnn, где nnnnn - это идентификатор раздела, связанный с задачей уменьшения. Содержит ли map/reduce объединить эти файлы? Если да, то как?

Ответ 1

Вместо того, чтобы выполнять слияние файлов самостоятельно, вы можете делегировать все слияние файлов с уменьшением выходных данных в hasoop, вызывая:

hadoop fs -getmerge /output/dir/on/hdfs/ /desired/local/output/file.txt

Ответ 2

Нет, эти файлы не объединены Hadoop. Количество файлов, которые вы получаете, совпадает с количеством сокращаемых задач.

Если вам нужно это в качестве ввода для следующего задания, не беспокойтесь о том, чтобы иметь отдельные файлы. Просто укажите весь каталог в качестве ввода для следующего задания.

Если вам нужны данные вне кластера, я обычно объединяю их на принимающей стороне, вытаскивая данные из кластера.

т.е. что-то вроде этого:

hadoop fs -cat /some/where/on/hdfs/job-output/part-r-* > TheCombinedResultOfTheJob.txt

Ответ 3

Что функция, которую вы можете использовать для объединения файлов в HDFS

public boolean getMergeInHdfs(String src, String dest) throws IllegalArgumentException, IOException {
    FileSystem fs = FileSystem.get(config);
    Path srcPath = new Path(src);
    Path dstPath = new Path(dest);

    // Check if the path already exists
    if (!(fs.exists(srcPath))) {
        logger.info("Path " + src + " does not exists!");
        return false;
    }

    if (!(fs.exists(dstPath))) {
        logger.info("Path " + dest + " does not exists!");
        return false;
    }
    return FileUtil.copyMerge(fs, srcPath, fs, dstPath, false, config, null);
}

Ответ 4

Только для текстовых файлов и HDFS в качестве источника и адресата используйте следующую команду:

hadoop fs -cat /input_hdfs_dir/* | hadoop fs -put - /output_hdfs_file

Это приведет к конкатенации всех файлов в input_hdfs_dir и выведет выход обратно в HDFS в output_hdfs_file. Имейте в виду, что все данные будут возвращены в локальную систему, а затем снова загружены в hdf, хотя временные файлы не создаются, и это происходит "на лету" с помощью UNIX pe.

Кроме того, это не будет работать с нетекстовыми файлами, такими как Avro, ORC и т.д.

Для двоичных файлов вы можете сделать что-то вроде этого (если у вас есть таблицы Hive, отображаемые в каталогах):

insert overwrite table tbl select * from tbl

В зависимости от вашей конфигурации это может также создать больше, чем файлы. Чтобы создать один файл, либо установите число редукторов на 1 явно с помощью mapreduce.job.reduces=1, либо установите свойство hive как hive.merge.mapredfiles=true.

Ответ 5

Вы можете запустить дополнительную задачу map/reduce, где карта и уменьшить не изменяют данные, а разделитель присваивает все данные одному редуктору.

Ответ 6

Файлы part-r-nnnnn генерируются после фазы уменьшения, обозначенной "r" между ними. Теперь факт: если у вас есть один редуктор, у вас будет выходной файл, например part-r-00000. Если количество редукторов равно 2, тогда вы будете иметь part-r-00000 и part-r-00001 и так далее. Посмотрите, если выходной файл слишком велик, чтобы вписаться в память устройства, так как инфраструктура hadoop была разработана для работы на Commodity Machines, тогда файл распадается. В соответствии с MRv1 у вас есть предел 20 редукторов для работы над вашей логикой. У вас может быть больше, но то же самое нужно настроить в конфигурационных файлах mapred-site.xml. Разговор о вашем вопросе; вы можете либо использовать getmerge, либо вы можете установить количество редукторов на 1, вставив следующий код в код драйвера

job.setNumReduceTasks(1);

Надеюсь, это ответит на ваш вопрос.

Ответ 7

Помимо моего предыдущего ответа, у меня есть еще один ответ для вас, который я пытался несколько минут назад. Вы можете использовать CustomOutputFormat, который выглядит как приведенный ниже код

public class VictorOutputFormat extends FileOutputFormat<StudentKey,PassValue> {

    @Override
    public RecordWriter<StudentKey,PassValue> getRecordWriter(
            TaskAttemptContext tac) throws IOException, InterruptedException {
        //step 1: GET THE CURRENT PATH
        Path currPath=FileOutputFormat.getOutputPath(tac);

        //Create the full path
        Path fullPath=new Path(currPath,"Aniruddha.txt");

        //create the file in the file system
        FileSystem fs=currPath.getFileSystem(tac.getConfiguration());
        FSDataOutputStream fileOut=fs.create(fullPath,tac);
        return new VictorRecordWriter(fileOut);
    }

}

Просто взгляните на четвертую строку от последней. Я использовал свое имя как имя выходного файла, и я протестировал программу с 15 редукторами. Тем не менее файл остается тем же. Таким образом, получение одного выходного файла вместо двух или более возможно еще очень четко, размер выходного файла не должен превышать размер первичной памяти, т.е. Выходной файл должен вписываться в память товарной машины, иначе может быть проблема с разделом выходного файла. Спасибо!!

Ответ 8

Почему бы не использовать свиньи script как этот для слияния файлов разделов:

stuff = load "/path/to/dir/*"

store stuff into "/path/to/mergedir"

Ответ 9

Если файлы имеют заголовок, вы можете избавиться от него, выполнив следующие действия:

hadoop fs -cat /path/to/hdfs/job-output/part-* | grep -v "header" > output.csv

затем добавьте заголовок вручную для output.csv

Ответ 10

. Содержит ли map/reduce объединить эти файлы?

Нет. Он не сливается.

Вы можете использовать IdentityReducer для достижения своей цели.

Выполняет уменьшение, записывая все входные значения непосредственно на выход.

public void reduce(K key,
                   Iterator<V> values,
                   OutputCollector<K,V> output,
                   Reporter reporter)
            throws IOException

Записывает все ключи и значения непосредственно на вывод.

Взгляните на соответствующие сообщения по теме:

hadoop: разница между редуктором 0 и редуктором идентичности?