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