質問

私は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に対する単一の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になります。ここに何かが欠けているに違いない。確かに高速で完全なクエリを実行する方法があります。

役に立ちましたか?

解決

私の推測では、左結合が必要だと思います。つまり、

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

例のこのブログエントリ

実際にJPAでこれを試したわけではないことに注意してください。しかし、多くの点でJPA標準の基礎であるHQLでうまく動作します。

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

他のヒント

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

バッチサイズが1(デフォルト)で、10人をロードする場合。次に、住所と会社のアイテムを読み取って繰り返し、hibernateは10人のユーザーに対して1つのクエリを実行し、それらのユーザーの1人に対して住所または会社が必要になるたびに、その人のアドレスに対してクエリを実行します。

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

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

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top