3

Hibernate の JPA 実装を使用していますが、フェッチされるエンティティごとに複数の SQL クエリが発行されるため、パフォーマンスが低下しています。結合された JPA クエリを使用すると、SQL クエリが 1 つだけ生成されますが、行が null 関係になることがわかりません。

例として、次の単純なスキーマを考えてみましょう。個人はある住所に住んでおり、会社に雇用されています。住所と雇用主はどちらもオプションであるため、null にすることができます。

@Entity
public  class Person {
    public name;

    @ManyToOne
    @Column(nullable=true)
    public Address address

    @ManyToOne
    @Column(nullable=true)
    public Company employer
}

@Entity
public  class Address {
    address attributes ...
}

@Entity
public  class Company {
    company attributes ...
}

上記には示されていませんが、各 JPA エンティティには何らかの ID (キー) があります。

@Id
public Integer id;

私が見ている問題は、Person に対する 1 つの JPA クエリが、データベースに対して複数の SQL クエリを生成することです。たとえば、次の JPA クエリ:

select p from Person p where ...

SQL クエリの結果:

select ... from Person where ...

また、取得した人物ごとに次の SQL クエリのペアも使用します。

select ... from Address a where a.id=xxx
select ... from Company c where c.id=yyy

これはパフォーマンスに大きな影響を与えます。クエリの結果セットが 1000 人の場合、1+1000+1000=2001 の SQL クエリが生成されます。

そこで、強制的に参加させて JPA クエリを最適化しようとしました。

select p from Person p join p.address a join p.employer e where ...

また:

select p, a, e from Person p join p.address a join p.employer e where ...

これにより、多数の結合を含む 1 つの SQL クエリが生成されます。問題は、住所または雇用主が null の場合、結合されたクエリでそれが見つからないことです。

そのため、遅い結合のないクエリを使用するか、行を取得しない高速の結合クエリを使用すると関係が null になります。ここで何かが欠けているに違いありません。確かに、高速で完全なクエリを実行する方法はあります。

4

2 に答える 2

3

私の推測では、左結合が必要になると思います。

SELECT p FROM Person p LEFT JOIN p.address a LEFT JOIN p.employer e WHERE...

例については、このブログエントリを参照してください

私は実際にJPAでこれを試したことがないことに注意してください。ただし、多くの点でJPA標準の基礎であるHQLでは正常に機能します。

プレーン結合で機能しない理由は、デフォルトが内部結合であるためです。

于 2009-01-03T02:44:54.320 に答える
0

Address エンティティと Company エンティティにバッチサイズ (@BatchSize) を設定してみてください。結合でそれらをロードすることはありません (それはあなたが求めていることですか?) が、1 つがロードされるたびにそれらの束をロードします。バッチサイズは、必要なことがわかったときにロードする必要がある数を示します。

バッチサイズが 1 (デフォルト) で、10 人をロードするとします。次に、それらを繰り返し、住所と会社の項目を読み取り、休止状態は 10 人に対して 1 つのクエリを実行します。次に、それらの人の住所または会社が必要になるたびに、その人の住所のクエリを作成します。

Address エンティティに 7 のバッチサイズを設定した場合、最初のアドレスを読み取ると、現在プロキシされているアドレスが 7 つ以上あることがわかり、7 つのアドレスを取得します。

BatchSize が 7 の Address と Company の両方があり、10 人を反復処理している場合、現時点で得られる 21 yo ではなく、5 つのクエリが発生します。まだ、結合によって得られる 1 ではありません。ただし、Person オブジェクトだけが必要で、そこに埋め込まれている Address/Company エンティティに触れない場合は、結合が遅くなります (個人 ID のリストを取得したい、または数を数えたいだけだとします)。男性/女性です)

見てください: http://hibernate.org/hib_docs/v3/reference/en/html/performance.html

于 2009-01-04T09:58:38.313 に答える