HDFSディレクトリに小さなファイルがたくさんあります。ファイルのボリュームは比較的小さいですが、ファイルあたりの処理時間は膨大です。つまり、TextInputFormat
のデフォルトの分割サイズである_64mb
_ファイルは、処理に数時間もかかります。
私がする必要があるのは、分割サイズを小さくするです。これにより、ジョブでさらに多くのノードを利用するができます。
質問は、_10kb
_と言うことでファイルを分割することはどのように可能ですか?このために独自のInputFormat
とRecordReader
を実装する必要がありますか、または設定するパラメーターはありますか?ありがとう。
パラメーターmapred.max.split.size
ジョブごとに個別に設定できるものを探しています。変更しないでくださいdfs.block.size
これはHDFSに対してグローバルであり、問題を引き起こす可能性があるためです。
Hadoop the Definitive Guide、page 203「デフォルトの最大分割サイズは、Java long型で表される最大値になります。ブロックサイズよりも小さい場合にのみ効果があります。 分割をブロックより小さくする。分割サイズは次の式で計算されます:
max(minimumSize, min(maximumSize, blockSize))
デフォルトで
minimumSize < blockSize < maximumSize
分割サイズはblockSize
です
例えば、
Minimum Split Size 1
Maximum Split Size 32mb
Block Size 64mb
Split Size 32mb
Hadoopは、多数の小さなファイルよりも少数の大きなファイルでより適切に動作します。この理由の1つは、FileInputFormatが、各分割が単一ファイルの全部または一部になるように分割を生成することです。ファイルが非常に小さく(「小さい」とはHDFSブロックよりもかなり小さいことを意味する)、それらの多くが存在する場合、各マップタスクはほとんど入力を処理せず、それらの多く(ファイルごとに1つ)があり、それぞれが追加の簿記オーバーヘッドを課します。 16 MBのブロックに分割された1 GBファイルと、10.000程度の100 KBファイルを比較します。 10.000ファイルはそれぞれ1つのマップを使用し、ジョブ時間は、単一の入力ファイルと16のマップタスクを使用した同等のファイルよりも数十倍または数百倍遅くなる場合があります。
ここに、魔法の構成文字列なしでここで必要なことを行う正しい方法を示すフラグメントがあります。必要な定数は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);
Combinfileinputformatを拡張するカスタム入力フォーマットを作成します[hadoopディストリビューションに独自の長所と短所があります]。入力分割をmapred.max.split.sizeで指定された値に結合します