2017-05-03 2 views
1

Ich habe eine große Sequenzdatei mit rund 60 Millionen Einträge (fast 4,5 GB). Ich möchte es teilen. Zum Beispiel möchte ich es in drei Teile mit jeweils 20 Millionen Einträgen aufteilen. Bisher ist mein Code wie folgt aus:Wie teilt man eine große Sequenzdatei in mehrere Sequenzdateien auf?

//Read from sequence file 
    JavaPairRDD<IntWritable,VectorWritable> seqVectors = sc.sequenceFile(inputPath, IntWritable.class, VectorWritable.class); 
    JavaPairRDD<IntWritable,VectorWritable> part=seqVectors.coalesce(3); 
    part.saveAsHadoopFile(outputPath+File.separator+"output", IntWritable.class, VectorWritable.class, SequenceFileOutputFormat.class); 

Aber leider jede der erzeugten Sequenzdateien ist um 4 GB zu (insgesamt 12 GB)! Kann jemand einen besseren/gültigen Ansatz vorschlagen?

+0

was Sie getan haben, ist der Weg zu gehen IMHO. Wenn Sie möchten, dass Dateien die gleiche Größe haben, verwenden Sie die Partition anstelle von –

+0

, aber die Neupartitionierung gibt einen Fehler -> 17/05/03 23:10:46 ERROR executor.Executor: Ausnahme in Aufgabe 1.0 in Stufe 0.0 (TID 1) com.esotericsoftware.kryo.KryoException: java.util.ConcurrentModificationException Serialisierung Spur: Klassen (sun.misc.Launcher $ AppClassLoader) classloader (org.apache.hadoop.mapred.JobConf) conf (org.apache.mahout .math.VectorWritable) ---- Detailspur ---> https://pastebin.com/eDWvV6Fx @TalJoffe – user3086871

+0

Ich denke, das Problem liegt im Mischen, denn wenn ich koalesce (3, wahr) das gleiche Problem ist geworfen! – user3086871

Antwort

1

Vielleicht nicht die genaue Antwort, die Sie suchen, aber es könnte sich lohnen, the second method for sequenceFile lesen, die, die ein minPartitions Argument dauert. Beachten Sie, dass coalesce, die Sie verwenden, nur die Partitionen verringern kann.

Der Code sollte dann wie folgt aussehen:

//Read from sequence file 
JavaPairRDD<IntWritable,VectorWritable> seqVectors = sc.sequenceFile(inputPath, IntWritable.class, VectorWritable.class, 3); 
seqVectors.saveAsHadoopFile(outputPath+File.separator+"output", IntWritable.class, VectorWritable.class, SequenceFileOutputFormat.class); 

Eine andere Sache, die Probleme verursachen kann, ist, dass einige SequenceFiles nicht spaltbar.

0

Vielleicht verstehe ich Ihre Frage nicht richtig, aber warum lesen Sie nicht einfach Ihre Datei Zeile für Zeile (= Eintrag für Eintrag?) Und bauen Sie Ihre drei Dateien auf diese Weise? Es wäre so etwas wie dieses:

int i = 0; 
List<PrintWriter> files = new ArrayList<PrintWriter>(); 
files.add(new PrintWriter("the-file-name1.txt", "UTF-8")); 
files.add(new PrintWriter("the-file-name2.txt", "UTF-8")); 
files.add(new PrintWriter("the-file-name3.txt", "UTF-8")); 
for String line in Files.readAllLines(Paths.get(fileName)){ 
    files.get(i % 3).writeln(line); 
    i++; 
} 

In diesem Fall wird eine Zeile alle drei Linie geht in die frist, die zweite und die dritte Datei.

Eine andere Lösung wäre, ein Binär lesen, wenn die Datei keine Textdatei ist, mit Files.readAllBytes(Paths.get(inputFileName)) und Schreiben in Ihre Ausgabedateien mit Files.write(Paths.get(output1), byteToWrite).

Allerdings habe ich keine Antwort darauf, warum die Ausgabe so viel mehr Platz in der Art nimmt, wie Sie es tun. Vielleicht ist die Codierung schuldig? Ich denke, Java codiert in UTF-8 standardmäßig und Ihre Eingabedatei könnte in ASCII codiert sein.

+0

Es ist keine Textdatei, es ist eine Sequenzdatei . Im Falle einer Textdatei könnte ich das leicht machen, ich kann auch einen zeilenweisen Ansatz für die Sequenzdatei nehmen, denke aber, ich suche nach dem besten Ansatz aus der Perspektive von funken rdd – user3086871

Verwandte Themen