6

解析して後で保持する必要があるテキスト ファイル ~6GB があります。「解析」することで、ファイルから 1 行 (通常は 2000 文字) を読み取り、その行から Car オブジェクトを作成し、後でそれを永続化します。

プロデューサー コンシューマー パターンを使用して解析と永続化を行っていますが、(パフォーマンス上の理由から) 一度に 1 つのオブジェクトを永続化するか、1 回のコミットで 1000 (またはその他の量) を永続化することに違いがあるかどうか疑問に思いますか?

現時点では、すべて (300 万行) を永続化するのに 2 時間以上かかります。

現在、私はこれをやっています:

public void persistCar(Car car) throws Exception
{
    try
    {
        carDAO.beginTransaction();  //get hibernate session...

        //do all save here.

        carDAO.commitTransaction(); // commit the session

    }catch(Exception e)
    {
        carDAO.rollback();
        e.printStackTrace(); 
    }
    finally
    {
        carDAO.close();
    }
}

デザインを変更する前に、このデザインの方が優れている理由があるかどうか (またはそうでない理由) を考えていました。また、セッションの開始/終了は高価と見なされますか?

public void persistCars(List<Car> cars) throws Exception
{
    try
    {
        carDAO.beginTransaction();  //get hibernate session...
        for (Car car : cars)    
        //do all save here.

        carDAO.commitTransaction(); // commit the session

    }catch(Exception e)
    {
        carDAO.rollback();
        e.printStackTrace(); 
    }
    finally
    {
        carDAO.close();
    }
}
4

1 に答える 1

5

伝統的に、休止状態は一括挿入ではうまくいきません。ある程度最適化する方法はいくつかあります。

API ドキュメントからこの例を取り上げます。

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();

上記の例では、20 個のエントリを挿入した後にセッションをフラッシュすると、操作が少し速くなります。

ここに同じことを議論する興味深い記事があります。

ストアド プロシージャを使用して一括挿入の別の方法を実装することに成功しました。この場合、パラメータを「|」として SP に渡します。分離されたリストであり、挿入スクリプトを SP 内に書き込みます。ここでのコードは少し複雑に見えるかもしれませんが、非常に効果的です。

于 2012-04-23T02:51:46.963 に答える