Изменить размер файла в Hadoop - PullRequest
23 голосов
/ 13 марта 2012

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

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

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

Ответы [ 5 ]

33 голосов
/ 13 марта 2012

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

22 голосов
/ 10 апреля 2012

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 генерирует разбиения таким образом, что каждое разбиение является всем или частью одного файла. Если файл очень маленький («маленький» означает значительно меньше, чем блок HDFS) и их много, то каждая задача карты будет обрабатывать очень мало входных данных, и их будет много (по одному на файл), каждый из которых накладывает дополнительные накладные расходы на бухгалтерию. Сравните файл размером 1 ГБ, разбитый на шестнадцать блоков по 64 МБ, и около 10000 файлов по 10000 КБ. 10.000 файлов используют одну карту каждый, и время выполнения задания может быть в десятки или сотни раз медленнее, чем эквивалентное с одним входным файлом и 16 задачами отображения.


3 голосов
/ 22 апреля 2015

Вот фрагмент, который иллюстрирует правильный способ сделать то, что здесь необходимо, без волшебных строк конфигурации.Необходимая константа определена внутри 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);
1 голос
/ 16 января 2013

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

0 голосов
/ 13 марта 2012

«Hadoop: полное руководство», с. 202

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

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

...