現在、JPAを使用しています。私が知りたいのは次のことです。
互いにマップされたテーブルがたくさんあります。ログを見ると、単純なクエリの後でデータベースから多くの情報が引き出されていることがわかります。一度に多くのクエリがあるとどうなりますか? それともうまくいきますか?どうすればパフォーマンスを向上させることができますか?
現在、JPAを使用しています。私が知りたいのは次のことです。
互いにマップされたテーブルがたくさんあります。ログを見ると、単純なクエリの後でデータベースから多くの情報が引き出されていることがわかります。一度に多くのクエリがあるとどうなりますか? それともうまくいきますか?どうすればパフォーマンスを向上させることができますか?
本当に多数のエンティティが一緒にマッピングされている場合、これは実際にパフォーマンスの問題につながる可能性があります。これは通常、@OneToMany
または@ManyToMany
マッピングが多数ある場合に当てはまります。
@Entity
public class A {
@OneToMany
private List<B> listB;
@ManyToMany
private List<C> listC;
@OneToMany
private List<D> listD;
...
}
ただし、できることの 1 つは、遅延フェッチを使用することです。これは、フィールドのロードが最初にアクセスされるまで遅延する可能性があることを意味します。fetch
属性を使用してこれを実現できます。
@Entity
public class A {
@OneToMany(fetch=FetchType.LAZY)
private List<B> listB;
@ManyToMany(fetch=FetchType.LAZY)
private List<C> listC;
@OneToMany(fetch=FetchType.LAZY)
private List<D> listD;
...
}
上記のサンプルでは、listB、listC、listD は、リストへの最初のアクセスまで DB からフェッチされないことを意味します。
遅延フェッチの具体的な実装は、JPA プロバイダーによって異なります。
ORM フレームワークにはオーバーヘッドが伴います。これはかなり高レベルであるため、1 行または 2 行の JPQL または純粋なEntityManager
操作で必要なものを取得するために、多くのネイティブ SQL クエリを生成する必要がある場合があります。
ただし、JPA は L1 と L2 の 2 つのキャッシュを使用します。1 つはエンティティ レベルで動作し、もう 1 つは PersistenceUnits レベルで動作します。したがって、大量の SQL クエリが生成されることがありますが、しばらくするとデータの一部がキャッシュされます。
パフォーマンスに不満がある場合は、遅延ロードされたコレクションを使用するか、必要なデータを自分でフェッチしてみてください (この件に関するBozho の投稿に興味があるかもしれません)。
最後に、キャッシュによってパフォーマンスが向上せず、手作りの JPQL クエリが正しく機能していないことがわかった場合は、いつでもプレーン SQL クエリに戻すことができます。これらのクエリは JPA キャッシュをバイパスし、ネイティブ クエリを実行する (またはアクティブなトランザクションの開始時に呼び出す) 前にいくつかのフラッシュを実行する必要がある場合があることに注意してください。
選択する最適化ルートに関係なく、まず自分の環境でテストし、この最適化が必要かどうかを自問自答してください。いくつかの重いテスト、パフォーマンス テストなどを行います。
「時期尚早の最適化は諸悪の根源です。」D. クヌート