HDFS に大量のデータを保存していますが、個々のファイルは非常に小さい (KB) です。そのため、MapReduce の処理に時間がかかっています。
処理時間を短縮できますか? SequenceFile は良い選択肢でしょうか?
複数の小さなテキスト ファイルを SequenceFile に変換する Java または MR コードを提供してください。
このようなシナリオでは、SequenceFile が適しています。次のようなことができます:
public class TextToSequenceConverter {
/**
* @param args
* @throws IOException
* @throws IllegalAccessException
* @throws InstantiationException
*/
@SuppressWarnings("deprecation")
public static void main(String[] args) throws IOException,
InstantiationException, IllegalAccessException {
// TODO Auto-generated method stub
Configuration conf = new Configuration();
conf.addResource(new Path("/hadoop/projects/hadoop-1.0.4/conf/core-site.xml"));
conf.addResource(new Path("/hadoop/projects/hadoop-1.0.4/conf/hdfs-site.xml"));
FileSystem fs = FileSystem.get(conf);
Path inputFile = new Path("/infile");
FSDataInputStream inputStream = fs.open(inputFile);
Path outputFile = new Path("/outfile");
IntWritable key = new IntWritable();
int count = 0;
Text value = new Text();
String str;
SequenceFile.Writer writer = SequenceFile.createWriter(fs, conf,outputFile, key.getClass(), value.getClass());
while (inputStream.available() > 0) {
key.set(count++);
str = inputStream.readLine();
value.set(str);
writer.append(key, value);
}
fs.close();
IOUtils.closeStream(writer);
System.out.println("SEQUENCE FILE CREATED SUCCESSFULLY........");
}
}
HAR ファイルも参照してください。
これを読むとよいかもしれません: http://blog.cloudera.com/blog/2009/02/the-small-files-problem/
HDFS ディレクトリ内のすべてのファイルを単一のシーケンス ファイルに変換するには:
package my.pack;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.Text;
public class BundleSeq {
/**
* @param args
* @throws IOException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void main(String[] args) throws IOException,
InstantiationException, IllegalAccessException {
// TODO Auto-generated method stub
Configuration conf = new Configuration();
conf.addResource(new Path(
"/hadoop/projects/hadoop-1.0.4/conf/core-site.xml"));
conf.addResource(new Path(
"/hadoop/projects/hadoop-1.0.4/conf/hdfs-site.xml"));
FileSystem fs = FileSystem.get(conf);
Path inputFile = new Path("/bundleinput");
Path outputFile = new Path("/outfile");
FSDataInputStream inputStream;
Text key = new Text();
Text value = new Text();
SequenceFile.Writer writer = SequenceFile.createWriter(fs, conf,
outputFile, key.getClass(), value.getClass());
FileStatus[] fStatus = fs.listStatus(inputFile);
for (FileStatus fst : fStatus) {
String str = "";
System.out.println("Processing file : " + fst.getPath().getName() + " and the size is : " + fst.getPath().getName().length());
inputStream = fs.open(fst.getPath());
key.set(fst.getPath().getName());
while(inputStream.available()>0) {
str = str+inputStream.readLine();
}
value.set(str);
writer.append(key, value);
}
fs.close();
IOUtils.closeStream(writer);
System.out.println("SEQUENCE FILE CREATED SUCCESSFULLY........");
}
}
ここで、ファイル名がキーで、ファイルの内容が値です。
を上書きorg.apache.hadoop.mapred.lib.CombineFileInputFormat
して作成することができますCombinedInputFormat
。実装については、こちらの回答を参照してください。パラメータmapred.max.split.size
を設定することで、入力ファイルを結合するサイズを制御できます。
詳細については、こちらをご覧ください。