2011-08-30 12 views
13

Hibernateは、N + 1問合せの問題を回避するための(少なくとも)2つのオプションを提供します。 1つはFetchModeをSubselectに設定することで、このIN節内にIN節と副選択を含む選択を生成します。もう1つはBatchSizeを指定することです。これは、親のIDを含むIN節で選択を生成します。Hibernate Subselect vs Batch Fetchching

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

私の質問は、HibernateのSubselect FetchModeをBatchSizeよりいつ使用するのですか? Subselectは親エントリが非常に多く(数千)、SubselectをBatchSizeにしたい場合はおそらく理にかなっています。

EDIT:熱心な負荷を扱う場合、2つの違いがあることに気付きました。 xToManyアソシエーションが熱心に、かつ副選択を通してロードされるように設定されている場合、それは怠け者であった場合と同じように副選択を生成します。ただし、BatchSizeを指定すると、生成されたクエリでは、別のクエリではなく外部結合が使用されます。熱心にロードする際にHibernateに別のバッチクエリを使用させる方法はありますか?

答えて

13

制御が難しいため、私は副選択を使用しません。複雑なビジネスロジックとそれに取り組んでいる大規模なシステムでは、どのクエリが使用されているかを言うのは難しいです。サブセレクトは、どのクエリが実行されているかを正確に把握している特定のケースで機能します。

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

+2

なぜsubselectを制御するのが難しいのか分かりません。いくつかの光を投げることができますか? –

+0

副選択は、以前に実行されたクエリに依存します。このクエリは非常に複雑である可能性があります。他の多くの表を使用し、索引付けされていない列でフィルタリングします。したがって、サブクエリのアプローチがパフォーマンスを向上させる可能性が高いかどうかは言い難いです。 –

+1

副選択に関するもう1つの問題は、MySQLで解決できます。 MySQL(5.5以下)は、ネストされたクエリを使用して強制的に相関関係を作成し、親クエリのすべての行についてそれらを再評価するため、ネストされたクエリでは驚異的なパフォーマンスを示します。私は、Hibernateが注釈付きリレーションのネストされたクエリを生成するための他の方法を見つけることができないので、副選択を避けると、MySQLで驚くようなことを防ぐことができます。 –

2

私はthis articleが役に立ちました。サブセレクトはコレクションにしか適用できませんが、バッチフェッチはコレクションと親の両方に適用できます。

コレクションのフェッチ戦略の場合、バッチ・フェッチをSQL文で複数回実行すると、副選択が1回実行されます(バッチ・サイズは事実上無限大です)。

関連する問題