Hibernateフェッチング戦略-“ join”を使用する場合そして、いつ“選択&#8221 ;?
質問
ほとんどのHibernate関連は" fetch"をサポートしています。パラメーター:
fetch="join|select"
" select"を使用デフォルト値です。
どのアソシエーションにどれを使用するかを決定する方法
すべてを" select"から変更しようとしました「参加」するアプリケーション全体-生成されるクエリの数はおそらく10倍減少しましたが、パフォーマンスはまったく同じままでした(わずかに悪化することさえあります)。
ありがとう。
解決
Joinはn + 1問題を解決することになっています。それぞれ10人の子供を持つ10人の親がいる場合、結合には1つのクエリが必要で、選択には11が必要です(各親の1つと各親の1つ)。データベースがアプリケーションと同じサーバー上にある場合、またはネットワークが非常に高速である場合、これは大した問題ではないかもしれませんが、各データベース呼び出しに遅延がある場合、合計することができます。すべての行で親列を複製しているため、最初のクエリではjoinメソッドの効率がやや劣りますが、データベースへの往復は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)
一方をもう一方の上に使用するタイミングについて...完全にはわかりません。データベースシステムに依存する可能性があります。一方が常に他方よりも優れている場合、彼らはあなたに選択肢を与えるのを煩わせるとは思いません!それぞれについて同様のパフォーマンスが見られる場合、私はそれについて心配しません。
親に多くの子があり、それらの子に他の多くの子がある場合、この場合、最初の「結合」がネットワークを詰まらせる可能性があります。私の提案は、この場合「選択」を使用して選択を分割することです。
fetch =&=" join" fetching =" join"を行う場合単一の選択ステートメントですべての情報を取得します。
fetch =&=" select" 関連付けられたコレクションを取得するために2番目のselectステートメントを一時停止する場合は、fetch =" select"を使用します。
source: Hibernate Fetching Strategies
JOINが推奨されます。
SELECTを使用する1つの理由は、多対多の関係を持つページング結果(オフセットと制限の設定)である場合です。 JOINを使用する場合、複数の多対多の子と「コピー」が含まれている場合、ルートエンティティは複数回表示されます。 (HibernateがDISTINCT_ROOT_ENTITYを使用して事実の後にそれらを折りたたむ場合でも)制限に対してカウントします。
人々は常に、 fetch = JOIN を使用してパフォーマンスヒットについて話します。しかし、私が推測しているように、フェッチする親/子レコードの数を理解することは重要です:
単一の親レコードのみを取得し、多くの子がないことを期待する場合は、 fetch = SELECT を使用することをお勧めします。
子を含むすべての親レコードを取得する場合は、 fetch = JOIN
を選択することをお勧めしますレコードが子を遅延的にフェッチしている場合( lazy = true )、 fetch = JOIN を使用しても意味がないことに注意してくださいすべての親レコードと子レコードが1回のショットで読み込まれます。