2017-09-14 21 views
0

私は巨大なCSV(1GB)をJavaコードで処理しています。java.lang.OutOfMemoryError大規模CSVファイルの処理中に

私のアプリケーションは、8GBのメモリを搭載した2コアマシンで動作しています。

以下のコマンドを使用してアプリケーションを起動します。

java -Xms4g -Xmx6g -cp $CLASSPATH JobSchedulerService 

Applcationは、S3からCSVをダウンロードして処理するスレッドを開始します。 アプリケーションはしばらくの間ファイルを処理しますが、OutOfMemoryErrorはファイルを半分処理しています。

私はCSVファイルの処理を続行すると同時に、メモリ使用量を低く抑える方法を模索しています。 CSVプロセスにおける

私は、次の手順を行っております:

//Step 1: Download FROM S3 
String bucketName = env.getProperty(AWS_S3_BUCKET_NAME); 
AmazonS3 s3Client = new AmazonS3Client(credentialsProvider); 
S3Object s3object = s3Client.getObject(new GetObjectRequest(bucketName, key)); 
InputStream inputSteam = s3object.getObjectContent(); //This Stream contains about 1GB of data 

//Step 2: Parse CSV to Java 
ObjectReader oReader = CSV_MAPPER.readerFor(InboundProcessing.class).with(CSV_SCHEMA); 
try (FileOutputStream fos = new FileOutputStream(outputCSV, Boolean.FALSE)) { 
    SequenceWriter sequenceWriter = CsvUtils.getCsvObjectWriter(InboundProcessingDto.class).writeValues(fos); 
    MappingIterator<T> mi = oReader.readValues(inputStream) 

    while (mi.hasNextValue()) { 
     InboundProcessing inboundProcessing = mi.nextValue(); 
     inboundProcessingRepository.save(inboundProcessing); // this is Spring JPA Entity Save operation. (Almost 3M records so 3M calls)      
     sequenceWriter.write(inboundProcessingDto); // this is writing to a CSV file on local file system which is uploaded to S3 in next Step 
    } 
} catch (Exception e) { 
    throw new FBMException(e); 
} 
+2

あなたはすべてを一度にメモリに読み込んでいるようです。それは必要ですか? – pvg

+1

あなたの開始コマンドが本当に 'java -Xms4g -Xms6g ...'を含んでいれば 'java -Xms4g -Xmx6g ...'に修正する必要があります。 – blafasel

+0

ありがとうございます。 これはタイプミスでした。 – Pramod

答えて

0

OOMの理由が見つかりました。 私は正しい方法でファイルを読んでいますが。ファイルを行ごとに読み込み、処理が完了したらすぐに古い行を破棄します。問題を生じさせないようにします。

問題は私がデータベースに書き込んでいるときです。

トランザクションが完了するまで、どのエンティティが解放されないかによって、自分のコードがトランザクションブロックで実行されます。要するに、すべての3Mエンティティは、トランザクションがコミットされるまでメモリ内に保持されます。

疑わしいオブジェクトにfinalizeメソッドを追加すると、この結論に達することができました。私が見ることができたのは、DTOS(一時的なPojo)は非常に速いスピードで廃棄されていますが、1つのエンティティも破棄されていないことです。最後にすべてのエンティティが破棄されました。

0

1)は、小さなサイズのファイルに大きなサイズのファイルを分割します。

2)各ファイルを順次または並列に処理します。小さなサイズで分割したファイルへ

チェックリンク:https://stackoverflow.com/a/2356156/8607192

それとも

使用するUNIXコマンド「分割の分割サイズに基づいて」。

関連する問題