データベースに対してあまりにも多くの SQL 呼び出しを実行している Hibernate を使用して、アプリケーションのパフォーマンスを改善しようとしています。呼び出しを減らしてパフォーマンスを向上させるために、データのフェッチをグループ化できると思いますが、ここでは少し迷っています。サブセレクトとバッチフェッチに関するHibernateのドキュメントを見てきましたが、これは役に立ちますが、問題が完全に解消されるとは思いません。
以下の例では、軍隊の一部である兵士のリストの詳細を取得し、それを Web ページに表示する必要があります。
@Entity
public class Troop {
@OneToMany(mappedBy="troop")
public List<Soldier> getSoldiers() {
...
}
フェッチ戦略をサブセレクト、バッチ、または熱心に設定して、SQL ステートメントをあまり使わずに、この軍隊のすべての兵士の部分を取得するのは簡単です。
@Entity
public class Soldier {
@Id
String soldierId
String firstName;
String lastName;
@OneToMany(mappedBy="address")
public List<Soldier> getAddress() {
...
@OneToMany(mappedBy="combatHistory")
public List<Soldier> getCombatHistory() {
...
@OneToMany(mappedBy="medicalHistory")
public List<Soldier> getMedicalHistory() {
...
}
各兵士エンティティには、遅延ロードされる他のエンティティとの複数の 1 対多の関係があります。これらのコレクションを初期化し、それらから値を取得する必要があります。Soldier に 3 つの一対多の関係があり、Troop に 1,000 人の兵士がいる場合、3 x 1,000 の SQL 呼び出しになります!
呼び出し回数を減らしてこれを最適化する方法はありますか? 取得する必要があるsoldierIdsは既にわかっているので、エンティティを取得して、最初のレベルのキャッシュで利用できるようにすることはできますか?
たとえば、クエリを実行できます
from Address as a where a.soldierId in (...)
from CombatHistory as a where a.soldierId in (...)
from MedicalHistory as a where a.soldierId in (...)
Address、CombatHistory などのエンティティをキャッシュできる場合、各兵士内でコレクションにアクセスするときに SQL 選択は実行されません。これにより、兵士ごとにコレクションごとに 1 回 (3 x 1000) ではなく、コレクションごとに 1 回 (この場合は 3 回) に呼び出しの数が減ります。
この問題への対処に関するドキュメントはあまり見られなかったので、ヒントやアイデアは大歓迎です。これらのコレクションはセットではなくリストであるため、左結合フェッチを複数のコレクションで実行できないことに注意してください。そうしないと、Hibernate が例外を返します。
HibernateException: cannot simultaneously fetch multiple bags