J'ai un tas de petits fichiers dans un répertoire HDFS. Bien que le volume de fichiers soit relativement petit, le temps de traitement par fichier est énorme . C'est-à-dire qu'un fichier 64mb
, qui correspond à la taille de division par défaut de TextInputFormat
, prendrait même plusieurs heures pour être traité.
Ce que je dois faire est de réduire la taille de la scission , afin de pouvoir utiliser encore plus de nœuds pour un travail.
La question est donc de savoir comment est-il possible de scinder les fichiers en disons 10kb
? Dois-je implémenter mes propres InputFormat
et RecordReader
pour cela, ou y a-t-il un paramètre à définir? Merci.
Le paramètremapred.max.split.size
qui peut être défini individuellement pour chaque travail correspond à ce que vous recherchez. Ne changez pasdfs.block.size
car cela est global pour HDFS et peut entraîner des problèmes.
Hadoop le guide définitif, page 203 "La taille de division maximale correspond par défaut à la valeur maximale pouvant être représentée par un type long Java. Elle n'a d'effet que si elle est inférieure à la taille du bloc, forçant les divisions à être inférieures à un bloc. La taille de la scission est calculée par la formule:
max(minimumSize, min(maximumSize, blockSize))
par défaut
minimumSize < blockSize < maximumSize
donc la taille de la division 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 gros fichiers qu'un grand nombre de petits fichiers. Une des raisons est que FileInputFormat génère des fractionnements de sorte que chaque fractionnement constitue tout ou partie d'un fichier unique. Si le fichier est très petit ("petit" signifie beaucoup plus petit qu'un bloc HDFS) et qu'il y en a beaucoup, chaque tâche de carte traitera très peu d'entrées et il y en aura beaucoup (une par fichier), dont chacun impose des frais généraux supplémentaires de comptabilité. Comparez un fichier de 1 Go divisé en seize blocs de 64 Mo et environ 10 000 fichiers de 100 Ko. Les 10 000 fichiers utilisent une carte chacun, et la durée du travail peut être plusieurs fois inférieure à celle d'une tâche équivalente avec un seul fichier d'entrée et 16 tâches de carte.
Voici un fragment qui illustre la manière correcte de faire ce qui est nécessaire ici sans chaînes de configuration magiques. La constante nécessaire est définie dans FileInputFormat
. La taille de bloc peut être prise si nécessaire à partir de la constante de bloc HDFS par défaut, mais elle a de bonnes chances d'être définie par l'utilisateur.
Ici, je divise simplement 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);
Ecrivez un format d’entrée personnalisé qui étend le fichier combineinfichierinputformat [a ses propres avantages et inconvénients pour la distribution hadoop] qui combine les divisions d’entrée dans la valeur spécifiée dans mapred.max.split.size