it-swarm.com.de

Ändern Sie die Größe der Dateiaufteilung in Hadoop

Ich habe eine Reihe kleiner Dateien in einem HDFS-Verzeichnis. Obwohl der Umfang der Dateien relativ klein ist, ist die Verarbeitungszeit pro Datei ist enorm. Das heißt, eine 64mb-Datei, die die standardmäßige Aufteilungsgröße für TextInputFormat ist, würde sogar mehrere Stunden dauern, um verarbeitet zu werden. 

Was ich tun muss, ist Reduzieren der Aufteilungsgröße, damit ich noch mehr Knoten verwenden für einen Job verwenden kann. 

Die Frage ist also, wie ist es möglich, die Dateien zu teilen, sagen wir 10kb? Muss ich dazu meine eigene InputFormat und RecordReader implementieren oder gibt es irgendwelche Parameter, die gesetzt werden müssen? Vielen Dank. 

22
Ahmedov

Sie suchen den Parametermapred.max.split.size, den Sie für jeden Job einzeln einstellen können. Ändern Sie nichtdfs.block.size, da dies für HDFS global ist und zu Problemen führen kann. 

32
Brainlag

Hadoop the Definitive Guide, Seite 217 "Die maximale Aufteilungsgröße ist standardmäßig auf den maximalen Wert eingestellt, der durch einen langen Java-Typ dargestellt werden kann. Sie hat nur dann eine Auswirkung, wenn sie kleiner als die Blockgröße ist, und erzwingt, dass Aufteilungen kleiner als a sind Block . Die Aufteilungsgröße wird nach folgender Formel berechnet:

max(minimumSize, min(maximumSize, blockSize))

standardmäßig

minimumSize < blockSize < maximumSize

die Aufteilungsgröße ist also blockSize

Zum Beispiel, 

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

Hadoop Funktioniert mit einer kleinen Anzahl von großen Dateien besser als mit einer großen Anzahl von kleinen Dateien. Ein Grund dafür ist, dass FileInputFormat Aufteilungen so generiert, dass jede Aufteilung alle oder Teile einer einzelnen Datei ist. Wenn die Datei sehr klein ist ("klein" bedeutet deutlich kleiner als ein HDFS-Block) und viele davon vorhanden sind, verarbeitet jede Map-Aufgabe nur sehr wenig Eingaben, und es gibt viele (eine pro Datei). jede von ihnen erhebt zusätzliche Buchhaltungskosten. Vergleichen Sie eine 1-GB-Datei, die in sechzehn 64-MB-Blöcke und etwa 10.000 100-KB-Dateien aufgeteilt ist. Die 10.000 Dateien verwenden jeweils eine Karte, und die Auftragszeit kann mehrere zehn oder hundert Mal langsamer sein als die entsprechende mit einer einzigen Eingabedatei und 16 Kartenaufgaben. 


21
Ahmedov

Hier ist ein Fragment, das den richtigen Weg veranschaulicht, um das zu tun, was ohne magische Konfigurationszeichenfolgen benötigt wird. Die benötigte Konstante wird in FileInputFormat definiert. Die Blockgröße kann bei Bedarf aus der Standard-HDFS-Blockkonstante entnommen werden, die Wahrscheinlichkeit, dass sie vom Benutzer definiert wird, ist jedoch recht gut.

Hier dividiere ich nur die maximale Aufteilungsgröße durch 2, wenn sie definiert wurde.

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);
3

Schreiben Sie ein benutzerdefiniertes Eingabeformat, das das Combinefileinputformat erweitert [hat seine eigenen Vor- und Nachteile für die Hadoop-Verteilung]. Dabei werden die Eingabeaufteilungen mit dem in mapred.max.split.size angegebenen Wert kombiniert

1