ほとんどのHibernateアソシエーションは、「フェッチ」パラメーターをサポートしています。
fetch="join|select"
「select」がデフォルト値です。
どの関連付けにどちらを使用するかを決定するにはどうすればよいですか?
すべてを「選択」から「参加」アプリケーション全体に変更してみました。生成されるクエリの数はおそらく10分の1に減少しましたが、パフォーマンスはまったく同じままでした(少しでも悪化しました)。
ありがとう。
Join は n+1 問題を解決するはずです。親が 10 人いて、それぞれに 10 人の子がいる場合、join には 1 つのクエリが必要で、select には 11 が必要です (各親の親に 1 つと子に 1 つ)。データベースがアプリケーションと同じサーバー上にある場合、またはネットワークが非常に高速である場合、これは大したことではないかもしれませんが、各データベース呼び出しに遅延がある場合は、それが加算される可能性があります。結合メソッドは、すべての行で親列を複製しているため、最初のクエリでは少し効率が低下しますが、データベースへの往復は 1 回だけです。
一般に、すべての親の子が必要になることがわかっている場合は、参加します。少数の親の子供だけが必要な場合は、select を使用します。
Select は、データベースに新しいクエリを発行して子アイテムをフェッチします。Join は、子アイテムを親のクエリに結合することによってフェッチします。そのため、クエリ数が減少しても、同様のパフォーマンスが見られます。
選択する:
SELECT * FROM parent WHERE id=(whatever)
SELECT * FROM child WHERE id=(parent.child.id)
加入:
SELECT *
FROM parent
LEFT OUTER JOIN child ON parent.child.id=child.id
WHERE parent.id=(whatever)
どちらをいつ使用するかについては...完全にはわかりません。おそらくデータベースシステムに依存します。どちらかが常に他のものよりも優れていた場合、彼らがわざわざあなたに選択肢を与えるとは思えません! それぞれに同様のパフォーマンスが見られる場合は、心配する必要はありません。
通常、パフォーマンス上の理由から、JOIN が推奨されます。
SELECT を使用する 1 つの理由は、多対多の関係を持つ結果をページングする (オフセットと制限を設定する) 場合です。JOIN を使用する場合、複数の多対多の子が含まれていて、それらの「コピー」が制限に対してカウントされる場合、ルート エンティティは複数回表示されます (たとえ Hibernate が DISTINCT_ROOT_ENTITY を使用した後にそれらを折りたたんだとしても)。