2017-12-08 18 views
1

私はSpring MVC 4、Spring Batch 3、Hibernate 5、およびEhcache 2.8を使用しています。 Spring Batchを使用して、1000のチャンクでHibernateを使用してCSVから多くのデータをインポートしています。Springバッチ、EhCache、およびHibernateを使用したデータインポートの漸進的パフォーマンス低下

まず、チャンク間の間隔は10秒以内です。徐々に、約10万アイテム後、アイテム間の間隔は1分以上です。私は、これが徐々に劣化するので、キャッシングの問題ではないかと考えています。私の現在の休止状態の統計がある

  • 第二レベルのキャッシュヒット%:97.8839177750907
  • クエリキャッシュヒット%:54.206282344445775
  • クエリ最大時間:

ここでは、インポートに使用するクエリで4.08s私のehcache.xml設定です

<defaultCache 
    eternal="false" 
    timeToIdleSeconds="180" 
    timeToLiveSeconds="240" 
    maxEntriesLocalHeap="10000" 
    maxEntriesLocalDisk="50000" 
    > 
    <persistence strategy="localTempSwap" /> 
</defaultCache> 

<cache name="org.hibernate.cache.internal.StandardQueryCache" 
    maxEntriesLocalHeap="10000" 
    maxEntriesLocalDisk="50000" 
    eternal="false" 
    timeToIdleSeconds="180" 
    timeToLiveSeconds="240" 
    > 
    <persistence strategy="localTempSwap" /> 
</cache> 

<cache name="org.hibernate.cache.spi.UpdateTimestampsCache" 
    eternal="false" 
    maxEntriesLocalHeap="0" 
/> 

[編集]ここはバッチジョブのソースコードです

@Bean 
@StepScope 
public static FlatFileItemReader<CsvPayment> paymentReader(@Value("#{jobParameters[fullPathFileName]}") String pathToFile, 
                  @Value("#{jobParameters[delimeter]}") String delimeter, 
                  @Value("#{jobParameters[skipItems]}") Long skipItems, 
                  @Value("#{jobParameters[limitItems]}") Long limitItems) 
{ 
    FlatFileItemReader<CsvPayment> reader = new FlatFileItemReader<>(); 

    reader.setResource(new FileSystemResource(pathToFile)); 
    reader.setEncoding(GlobalConstants.UTF8); 
    reader.setMaxItemCount(limitItems.intValue()); 
    reader.setLinesToSkip(skipItems.intValue()); 
    reader.setLineMapper(new CsvPaymentLineMapper(delimeter)); 

    return reader; 
} 

@Bean("importPayment") 
public Job importPayment(ItemReader<CsvPayment> paymentReader) 
{ 
    return jobBuilderFactory.get("paymentReader").incrementer(new RunIdIncrementer()).flow(
     paymentStep1(paymentReader)).end().build(); 
} 

@Bean 
public Step paymentStep1(ItemReader<CsvPayment> paymentReader) 
{ 
    return stepBuilderFactory.get("paymentStep1").<CsvPayment, OccupancyPayment> chunk(CHUNK_SIZE).reader(
     paymentReader).processor(itemProcessor).faultTolerant().listener(
      new ChunkListenerImpl(logger)).writer(itemWriter()).build(); 
} 

@Bean 
public HibernateItemWriter<OccupancyPayment> itemWriter() 
{ 
    HibernateItemWriter<OccupancyPayment> itemWriter = new HibernateItemWriter<>(); 
    itemWriter.setSessionFactory(sessionFactory); 
    itemWriter.setClearSession(true); 
    return itemWriter; 
} 

うまくいけば、誰かが私に正しい方向を指摘することができます。ありがとう。

+0

第1レベルのキャッシュを消去します。各エンティティが第1レベルのキャッシュに追加され、クエリを発行するたびに、休止状態のオブジェクトの第1レベルキャッシュ(セッション/エンティティマネージャ)がチェックされます。オブジェクトの数が増えるほど時間がかかります。 –

+0

@ M.Deinum Spring Batchで使用しているHibernateItemWriterはAPIで、各書き込みで最初のレベルのキャッシュをクリアしていると言います。私はバッチジョブのソースコードを提供するために投稿を更新します。 –

+0

プロセッサが見つかりません。 –

答えて

0

セッションキャッシュが大きくなり、アプリの処理速度が遅くなり、メモリを消費します。 hereから取ら

Session session = sessionFactory.openSession(); 
Transaction tx = session.beginTransaction(); 

for (int i=0; i<100000; i++) { 
    Customer customer = new Customer(.....); 
    session.save(customer); 
    if (i % 20 == 0) { //20, same as the JDBC batch size 
     //flush a batch of inserts and release memory: 
     session.flush(); 
     session.clear(); 
    } 
} 

tx.commit(); 
session.close(); 

例を、私たちは同じソリューションを使用して、あなたに確認し、それが良い作品:

これを試してみてください。

解決策の唯一の欠点は、時にはHibernateからNonUniqueObjectExceptionが得られることです。 session.clear()の結果として、すべてのHibernateインスタンスがデタッチされます。。そのような場合は、間違いなくthisを読んで、おそらくsession.refresh(instance)に電話する必要があります。

+0

これはスプリングバッチではありません。ご存じのように、Springバッチはコミットをチャンクに分割して、データを徐々に表示することができます。 250,000個の挿入に1回コミットすることは私の場合には理想的ではありません –

関連する問題