0

次のコード行があります。

log4net.LogManager.GetLogger("m").Debug(DateTime.Now.ToString("hh:mm:ss.fff") + "Check-1");

Setting setting = session.CreateQuery("from Settings s").UniqueResult< Setting>();

log4net.LogManager.GetLogger("m").Debug(DateTime.Now.ToString("hh:mm:ss.fff") + "Check-2");

上記のコードはミリ秒未満で実行されます (Check-1 と Check-2 の時間は同じで、時間はミリ秒単位で測定され、使用される基準はコードに示されていません)。

しかし、この場合:

IList< チケット> チケット = session.CreateQuery("チケットから").List< チケット>();

foreach(チケットのチケット t)
{
t.Dosomething = 5;
log4net.LogManager.GetLogger("m").Debug(DateTime.Now.ToString("hh:mm:ss.fff") + "Check-1"); Setting setting = session.CreateQuery("from Settings s").UniqueResult< Setting>(); log4net.LogManager.GetLogger("m").Debug(DateTime.Now.ToString("hh:mm:ss.fff") + "Check-2");
}

上記のコードは、大量のデータを処理する巨大な処理コードの単純化されたバージョンであり、foreach ループで別のクエリが必要でした。forech ループのクエリは 500 ミリ秒で実行されます。チケット コレクションには 15000 行が含まれます。

私はすでにコードをリファクタリングしました (foreach にクエリはありません) が、同じクエリを単独で実行すると実行に時間がかからず、最初に大量のエンティティが読み込まれた後に実行すると非常に遅くなる理由に興味がありますか?

しかし、上記の同じシナリオで、2 番目のクエリに別のセッションを使用すると、すぐに実行されました。

膨大な量のエンティティの foreach ループで別のクエリを実行する必要がある場合に、そのようなケースに対処する方法についての推奨事項はありますか?

4

3 に答える 3

2

NHibernateはデフォルトで、セッションにロードされたオブジェクトを追跡します(第1レベルのキャッシュ)。クエリが行われると、NHibernateは、ロードされたオブジェクトの一部にクエリの結果に影響を与える可能性のある変更があるかどうかをチェックします。クエリが正しい結果を返すことができるように、そのような変更をデータベースにフラッシュする必要があります。ロードされるオブジェクトが多いほど、このプロセスにかかる時間が長くなります。

NHibernateとISessionは、ロードされるオブジェクトの数が比較的少ないように最適化されていますが、これは問題ではありません。

これらは、バッチシナリオのパフォーマンスを改善するためのいくつかのトリックです。

  • 作業を、別々のトランザクションとセッションで独立して実行できる小さな部分に分割してみてください。

  • 作業をより小さな部分に分割した場合はsession.Flush()session.Clear()戦略的なポイント(各独立した部分の後)で変更をフラッシュし、追跡されるオブジェクトの量を妥当なレベルに保つために使用できます。この戦略では、すべてのパーツを同じトランザクションで実行できます。

  • session.FlushModeauto-flush-on-queryを無効にする方法を見てください。を使用するFlushMode.CommitNever、への明示的な呼び出しと組み合わせますFlush()。ただし、クエリの結果は、同じ作業単位で以前に実行された変更を反映していない場合があります。

于 2013-03-06T09:37:41.707 に答える
1

チケットを繰り返し処理する前に、プロジェクションを使用してチケットを DTO にロードしてみてください。プロジェクションを使用して必要なデータだけをロードすることは、Hibernate がオブジェクトをロードして追跡する必要がないことを意味します。

于 2013-03-05T16:05:05.893 に答える
0

最初のテーブルレコードをフェッチし、繰り返して2番目のテーブルレコードをフェッチするよりも、2つのテーブルを結合して結果を取得する方が常に適切です。

より多くの要件を与える

于 2013-03-05T16:09:00.550 に答える