Modifier la taille du fichier Split dans Hadoop
j'ai un tas de petits fichiers HDFS répertoire. Bien que le volume des dossiers soit relativement petit, le temps de traitement par fichier est énorme. C'est, un 64mb
file, qui est la taille de division par défaut pour TextInputFormat
, prendrait même plusieurs heures à être traitée.
ce que je dois faire, c'est réduire la taille du segment, pour que je puisse utiliser encore plus les nœuds pour un emploi.
donc la question est, comment est-il possibilité de diviser les fichiers par disons 10kb
? Ai-je besoin pour mettre en place mes propres InputFormat
et RecordReader
pour cela, ou est-il un paramètre à régler? Grâce.
5 réponses
Le paramètre mapred.max.split.size
ce qui peut être défini par tâche individuellement est ce que vous recherchez. Ne pas changer dfs.block.size
parce que ceci est global pour les HDFS et peut conduire à des problèmes.
Hadoop the Definitive Guide, page 203 "Le maximum de diviser la taille par défaut est la valeur maximale qui peut être représenté par un Java de type long. Il n'a d'effet que lorsqu'elle est inférieure à la taille de bloc, forçant se divise pour être plus petit qu'un bloc. La scission de la taille est calculée par la formule:
max(minimumSize, min(maximumSize, blockSize))
par défaut
minimumSize < blockSize < maximumSize
donc la taille de split est blockSize
Par exemple,
Minimum Split Size 1
Maximum Split Size 32mb
Block Size 64mb
Split Size 32mb
Hadoop Fonctionne mieux avec un petit nombre de fichiers volumineux qu'un grand nombre de petits fichiers. Une des raisons en est que FileInputFormat génère des fentes de telle sorte que chaque fente est tout ou partie d'un seul fichier. Si le fichier est très petit ("petit" signifie beaucoup plus petit qu'un bloc HDFS) et qu'il y en a beaucoup, alors chaque tâche de mappage traitera très peu d'entrées, et il y en aura beaucoup (une par fichier), chacune d'entre elles imposant des frais supplémentaires de comptabilité. Comparez un fichier de 1 Go divisé en 16 blocs de 64 Mo, et 10.000 environ 100KB fichiers. Les 10.000 fichiers utilisent une map chacun, et le temps de travail peut être des dizaines ou des centaines de fois plus lent que l'équivalent avec un seul fichier d'entrée et 16 tâches de map.
voici fragment qui illustre la façon correcte de faire ce qui est nécessaire ici sans chaînes de configuration magiques. La constante nécessaire est définie à l'intérieur de FileInputFormat
. La taille du bloc peut être prise si nécessaire à partir de la constante de bloc HDFS par défaut, mais il a une assez bonne probabilité d'être défini par l'utilisateur.
ici, je divise juste la taille de division maximale par 2 si elle a été définie.
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);
Écrire un format d'entrée personnalisé qui étend combinefileinputformat[a ses propres avantages et inconvénients de base dans la distribution hadoop]. qui combine les entrées se divise dans la valeur spécifiée dans mapred.Max.Split.taille
étant donné un ensemble de fichiers, comment FileInputFormat les transforme-t-il en divisions? FileInputFormat ne divise que les gros fichiers. Ici "Grand" signifie plus grand qu'un bloc HDFS. la taille de split est normalement celle d'un HDFS bloc.
vous devriez donc changer la taille du bloc HDFS, mais ce n'est pas la bonne façon. Peut-être que vous devriez essayer de revoir l'architecture de votre application MapReduce.