SpringデータJPA(現在4.0.8)とHibernate(現在4.2.16)を使用しているため、JPA OneToManyリストの副選択ヒットへのページネゴシエーションに問題があります。内部リストでは、副選択は、指定されたページの主要素だけでなく、主要素と結合するすべての要素を選択します。Spring Data JPA OneToManyページングFetchType subselect
例えば:
主JPAエンティティ:JPAエンティティのプライマリリストを取得するために生成される
@Entity
@NamedQuery(name="Message.findAll", query="SELECT m FROM Message m")
public class Message implements Serializable {
...
//uni-directional many-to-one association to Message_Review
@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
@JoinColumn(name="message_id", referencedColumnName="message_id", insertable=false, updatable=false)
@Fetch(FetchMode.SUBSELECT)
private Set<Message_Review> messageReviews;
SQLのようなある:のベースリスト後
SELECT TOP ? MESSAGE0_.MESSAGE_ID AS MESSAGE_1_0_, MESSAGE0_....... AND NOT (EXISTS (SELECT MESSAGEREV1_.MESSAGE_ID, MESSAGEREV1_.......))
JPAエンティティ、Spring Data JPA(またはHibernate)は、(@ FetchMode.SUBSELECTごとに)OneToManyリストを照会します。
SELECT messagerev0_.message_id as message_2_0_1_,
.....
where messagetop0_.message_id in
(select message0_.message_id
from .......
)
OneToManyヒットのインナーセレクトには、TOPが関連付けられていないことに注意してください。したがって、メッセージレビューのすべてを元に戻しています(JPAがそれにマッチさせる必要があるものだけではなく)。通常、これは大きな問題ではありませんが、OneToManyリストに実質的に大きなデータセットがある場合、ペイロードは、特定のページに対して非常に小さなサブセットしか必要としない場合、データベースから数百万のアイテムを戻す可能性があります。
@ FetchMode.SubSelectを利用してSQLヒット数を制限すると、ページングをOneToManyに引き継ぐ方法についてのアイデアはJPAエンティティでリストされていますか?
私はこれが私が行方不明であると信じています。エンティティのBatchSizeを設定することの欠点は何ですか? (あなたがEAGERの初期化を使用している場合は、それが理由で「1」にデフォルト設定されていると仮定します)? – LetsBeFrank
バッチサイズが大きければ大きいほど、メモリ消費量は大きくなります。必要なCPUが増えます。私は、バッチサイズを低く保つことは、限られたリソースを持つデバイスに適していると思います。 Hibernateチュートリアルを開くと、@ BatchSizeがパフォーマンスチューニングの章で説明されていることがわかります。 Subselect戦略と同じですが、サブセレクトは大きなデータセットに対して非常に重いことがあります。この点に関して、BatchSizeを使用することは、N + 1選択問題と同時にメモリ消費量を低く抑えるという点で優れた妥協点です。 –