web-dev-qa-db-ja.com

Hibernateフェッチ戦略-「結合」を使用する場合と「選択」を使用する場合

ほとんどのHibernateアソシエーションは、「フェッチ」パラメーターをサポートしています。

fetch="join|select"

「選択」がデフォルト値です。

どのアソシエーションにどのものを使用するかを決定する方法は?

すべてを「選択」から「結合」アプリケーション全体に変更しようとしました-生成されたクエリの数はおそらく10倍減少しましたが、パフォーマンスはまったく同じままでした(わずかに悪化することもあります)。

ありがとう。

47
serg

結合はn + 1問題を解決することになっています。 10の親があり、それぞれに10の子がある場合、結合には1つのクエリが必要で、選択には11が必要です(親ごとに1つ、各親の子に1つ)。データベースがアプリケーションと同じサーバー上にある場合、またはネットワークが非常に高速である場合、これは大した問題ではないかもしれませんが、各データベース呼び出しに遅延がある場合、合計することができます。すべての行で親列を複製しているため、データベースへの往復は1回だけなので、最初のクエリではjoinメソッドの効率はやや劣ります。

一般に、すべての親の子供が必要になることがわかっている場合は、参加します。少数の親の子供だけが必要な場合は、selectを使用します。

41
Brian Deterling

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つを使用するかに関して...全体は確かではありません。データベースシステムに依存する可能性があります。一方が常に他方よりも優れていた場合、彼らはあなたに選択肢を与えるのを煩わせるとは思わない!それぞれのパフォーマンスが似ているのであれば、心配する必要はありません。

9
jdmichal

親に多数の子があり、それらの子に他の多くの子がある場合、この場合、最初の「結合」がネットワークを詰まらせる可能性があります。私の提案は、この場合「選択」を使用して選択を分割することです。

2
MullaBihari

通常、パフォーマンス上の理由から、JOINが推奨されます。

SELECTを使用する1つの理由は、多対多の関係を持つ結果をページングする(オフセットと制限を設定する)場合です。 JOINを使用する場合、ルートエンティティに複数の多対多の子が含まれ、それらの「コピー」が制限にカウントされる場合(ルートがDISTINCT_ROOT_ENTITYを使用した後に折りたたまれても)、複数回表示されます。

1
Daedalus

fetching = "join"fetching = "join"を実行すると、1つのselectステートメントですべての情報が取得されます。

fetching = "select"2番目のselectステートメントを一時停止して、関連するコレクションを取得する場合は、fetch = "select"を使用します。

source: Hibernate Fetching Strategies

1
user528050

人々はfetch = JOINを使用して常にパフォーマンスヒットについて話します。しかし、私が推測しているように、フェッチする親/子レコードの数を理解することは重要です。

単一の親レコードのみを取得し、多くの子がないことを期待する場合は、fetch = SELECTを使用することをお勧めします。

子を含むすべての親レコードを取得する場合は、fetch = JOINを選択することをお勧めします

レコードを子(lazy = true)で遅延フェッチしている場合、fetch = JOINを使用しても意味がありません。親と子のレコードは1回のショットでロードされます。

0
Jagadeesh