Подтвердить что ты не робот

Изменить размер разделяемого файла в Hadoop

У меня есть куча небольших файлов в каталоге HDFS. Хотя объем файлов относительно невелик, объем обработки в файле огромен. То есть, файл 64mb, который является разделенным по умолчанию размером для TextInputFormat, занимает несколько часов для обработки.

Что мне нужно сделать, это уменьшить размер разделения, чтобы я мог использовать еще больше узлов для задания.

Итак, вопрос в том, как можно разбить файлы, скажем, 10kb? Нужно ли мне реализовать мои собственные InputFormat и RecordReader для этого, или есть ли какой-либо параметр для установки? Благодарю.

4b9b3361

Ответ 1

Параметр mapred.max.split.size, который может быть установлен для отдельного задания, - это то, что вы ищете. Не меняйте dfs.block.size, потому что это глобально для HDFS и может привести к проблемам.

Ответ 2

Hadoop the Definitive Guide, стр. 203 "Максимальный размер разделения по умолчанию равен максимальному значению, которое может быть представлено длительным типом Java. Он имеет эффект только тогда, когда он меньше размера блока, форсирует разделение на меньше блока. Размер разделения рассчитывается по формуле:

max(minimumSize, min(maximumSize, blockSize))

по умолчанию

minimumSize < blockSize < maximumSize

поэтому размер разделения blockSize

Например,

Minimum Split Size 1
Maximum Split Size 32mb
Block Size  64mb
Split Size  32mb

Hadoop работает лучше с небольшим количеством больших файлов, чем с большим количеством небольших файлов. Одна из причин этого заключается в том, что FileInputFormat генерирует разбиения таким образом, что каждый split является полностью или частично одним файлом. Если файл очень маленький ( "маленький" означает значительно меньше, чем блок HDFS), и их много, тогда каждая задача карты будет обрабатывать очень мало ввода, и их будет много (по одному на файл), каждый из которых налагает дополнительные накладные расходы. Сравните файл 1gb, разбитый на шестнадцать блоков размером 64 МБ, и 10 000 или около 100 КБ файлов. 10.000 файлов используют по одной карте каждый, а время работы может быть в десятки или сотни раз медленнее, чем эквивалентное, с одним входным файлом и 16 задачами карты.


Ответ 3

Вот фрагмент, который иллюстрирует правильный способ делать то, что здесь нужно, без магических строк конфигурации. Необходимая константа определена внутри FileInputFormat. Размер блока может быть взят, если необходимо, с постоянной константы блока HDFS по умолчанию, но имеет довольно хорошую вероятность определить пользователя.

Здесь я просто разделил максимальный размер разделения на 2, если он был определен.

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

// ....

final long DEFAULT_SPLIT_SIZE = 128 * 1024 * 1024;
final Configuration conf = ...

// We need to lower input block size by factor of two.
conf.setLong(
    FileInputFormat.SPLIT_MAXSIZE,
    conf.getLong(
        FileInputFormat.SPLIT_MAXSIZE, DEFAULT_SPLIT_SIZE) / 2);

Ответ 4

Напишите пользовательский формат ввода, который расширяет формат combfileinputformat [имеет свои собственные плюсы и минусы, основываясь на распределении hadoop]. который объединяет входные расщепления в значение, указанное в mapred.max.split.size

Ответ 5

"Hadoop: окончательное руководство", стр. 202:

Учитывая набор файлов, как FileInputFormat превращает их в разбиения? FileInputFormat разделяет только большие файлы. Здесь "большой" означает больше, чем блок HDFS. Размер разделения обычно равен размеру HDFS блок.

Итак, вы должны изменить размер блока HDFS, но это неверно. Возможно, вам стоит попытаться просмотреть архитектуру вашего приложения MapReduce.