7

私は顧客とのManyToOne関係を持つJPAエンティティOrderを持っています。これは双方向であるため、Customer にも OneToMany フィールドの注文があります。どちらの関係も EAGER フェッチングを使用します (または OpenJPA フェッチプランにあります)。

Order から選択すると、注文に対して 1 つの選択が取得され、Customer.orders フィールドに対して N の選択が取得されます。驚いたことに、この問題は、JOIN FETCH (一方向の場合に機能します) を使用している場合でも、OpenJPA、EclipseLink、および Hibernate に存在します。

これを解決する良い方法はありますか?より複雑なグラフの N+1 選択問題を解決するソリューションはありますか?

編集: 私自身の研究の結果: - OpenJPA (私が使用している) の場合、解決策はまだわかりません - Hibernate @Fetch(FetchMode.SUBSELECT) の場合、問題は解決します。@BatchSize を使用することも役立ちます。これにより、指定された数の customer.orders フィールドが同時に選択されます。- EclipseLink の場合、同様の機能 @BatchFetch(value=BatchFetchType.IN) を見つけましたが、この場合は役に立ちません。双方向の関係でこれを効率的に処理できないと思います。

4

3 に答える 3

1

ご覧ください: SELECT N+1 とは? 良い情報がたくさんあるので。

Hibernate を使用している場合: Hibernate - 第 19 章: パフォーマンスの向上 - フェッチ戦略

私自身の個人的な解決策は、ネイティブ SQL と tmp ids テーブルを使用することです。これは、一般に、N + 1 選択の問題は主にバッチ処理の問題であるためです。それ以外の場合は、遅延読み込み (通常は N+1 ソリューション) を使用すると、パフォーマンスが向上する可能性があります。

于 2012-11-15T15:50:54.250 に答える
0

ここに解決策があります:

  1. エンティティ レイヤーを API レイヤーから分離し、アプリケーション内でのみ API インスタンスとやり取りします。このコンテキストでの API は、DTO と呼ばれることもあります。

  2. エンティティから関係を完全に削除します。

  3. 子をフェッチすることを示すメカニズムを作成します。例: fetchRequestList を、API をエンティティにマップするレイヤーに伝達します (これにより、条件付きでフェッチできます)。

  4. クエリの実行中に、通常どおりに親オブジェクトを収集します。

  5. 親 PK への FK に基づく IN 句を含む名前付きパラメーター化クエリを使用して、子のコレクション全体を取得します。

  6. 結果をループして、それらを親に一致させます。

これにより、ORM は n(n+1) クエリではなく n+1 クエリを実行するようになります。カスタムロジックを使用して、カスケード保存、削除、更新などを実装する必要があることに注意してください。

于 2016-10-15T16:19:15.513 に答える
-1

どの ORM フレームワークでも、N+1 問題はよくあることです。それを避けることはできません。しかし、これは、問題を解決するためにどのようなアプローチを取るかについての詳細です. 実装に基づいて、関連付けと遅延ロードまたは熱心なロードの日付を使用できます。データベースのマッピングを実行し、関連するすべてのデータを単一のクエリで取得して、それをモデルにマッピングすることもできます。データベースはインデックス化されているため、この操作はデータを取得して N+1 クエリを使用してマッピングするよりも高速です (ネットワークの待機時間が許せば)。

于 2012-11-15T15:42:06.347 に答える