15

Hibernateは、N + 1クエリの問題を回避するための(少なくとも)2つのオプションを提供します。1つは、FetchModeをSubselectに設定することです。これにより、IN句を含むselectと、このIN句内のsubselectが生成されます。もう1つは、BatchSizeを指定することです。これにより、親のIDを含むIN句を使用してselectが生成されます。

どちらも機能しますが、親のクエリが複雑なため、[サブ選択]オプションでパフォーマンスの問題が発生することがよくあります。一方、BatchSizeが大きい場合(たとえば1000)、クエリの数とそれらのクエリの複雑さは非常に小さくなります。

したがって、私の質問は、BatchSizeではなくHibernateのSubselectFetchModeをいつ使用するのかということです。親エントリの数が非常に多い場合(数千)、副選択はおそらく意味がありますが、BatchSizeよりも副選択を使用したいシナリオは他にありますか?

編集:熱心な読み込みを処理するときに、2つの違いに気づきました。xToManyアソシエーションを熱心にロードし、サブセレクトを介してロードするように設定している場合、レイジーの場合と同じようにサブセレクトが生成されます。ただし、BatchSizeを指定すると、生成されたクエリは、個別のクエリではなく外部結合を使用します。熱心にロードするときにHibernateに個別のバッチクエリを使用させる方法はありますか?

4

2 に答える 2

14

制御が難しいので、副選択は使用しません。複雑なビジネスロジックとそれに取り組んでいる大規模なチームを持つ非常に大規模なシステムでは、どのクエリが使用されているかを判断するのは非常に困難です。副選択は、実行されるクエリが正確にわかっている特定の場合に機能する場合があります。

バッチフェッチにはいくつかの大きな利点があります。常に最速とは限りませんが、通常は十分に高速です。一方、非常に安定しており、副作用がなく、ビジネスロジックに対して完全に透過的です。100を超えるバッチ値を使用することはありません。N+1を妥当な量のクエリに減らすだけで十分です。

于 2011-08-30T06:28:10.317 に答える
2

この記事は役に立ちました。バッチフェッチはコレクションと親の両方に適用できますが、副選択はコレクションにのみ適用できると思います。

コレクションのフェッチ戦略の場合、副選択は1回実行されますが(バッチサイズは事実上無限大であるため)、バッチフェッチではSQLステートメントが複数回実行される可能性があります。

于 2012-06-29T12:11:45.393 に答える