30.7. 最適化ローディング
最適化ローディングは、数が最も少ないクエリーにおける処理を完了させるのにデータのロードを必要最小限に抑えることが目的です。JBoss の調整は、ロードプロセスに関する知識によります。このセクションでは、JBoss ロードプロセス内部とその設定について説明します。ロードプロセスを調整するには、ロードシステムに関する深い知識が必要であるため本章を繰り返し読むことをおすすめします。
30.7.1. ローディングのシナリオ
使用シナリオを参照するのが、ローディングについて調べる最も簡単な方法です。最も一般的なシナリオはエンティティのコレクションを検索し、操作を実行する検索結果を反復することです。以下の例に gangsters をすべて含む html テーブルの生成を示します。
public String createGangsterHtmlTable_none() throws FinderException { StringBuffer table = new StringBuffer(); table.append("<table>"); Collection gangsters = gangsterHome.findAll_none(); for (Iterator iter = gangsters.iterator(); iter.hasNext();) { Gangster gangster = (Gangster) iter.next(); table.append("<tr>"); table.append("<td>").append(gangster.getName()); table.append("</td>"); table.append("<td>").append(gangster.getNickName()); table.append("</td>"); table.append("<td>").append(gangster.getBadness()); table.append("</td>"); table.append("</tr>"); } return table.toString(); }
このコードが1つのトランザクションで呼び出され、ローディングの最適化がすべて無効になっていると仮定します。
findAll_none
の呼び出しで、JBoss は以下のクエリを実行します。
SELECT t0_g.id FROM gangster t0_g ORDER BY t0_g.id ASC
サンプルデータベースの 8 つの gangster それぞれにアクセスするため、JBoss は以下の 8 つのクエリーを実行します。
SELECT name, nick_name, badness, hangout, organization FROM gangster WHERE (id=0) SELECT name, nick_name, badness, hangout, organization FROM gangster WHERE (id=1) SELECT name, nick_name, badness, hangout, organization FROM gangster WHERE (id=2) SELECT name, nick_name, badness, hangout, organization FROM gangster WHERE (id=3) SELECT name, nick_name, badness, hangout, organization FROM gangster WHERE (id=4) SELECT name, nick_name, badness, hangout, organization FROM gangster WHERE (id=5) SELECT name, nick_name, badness, hangout, organization FROM gangster WHERE (id=6) SELECT name, nick_name, badness, hangout, organization FROM gangster WHERE (id=7)
このシナリオには 2 つ問題があります。1 つは、JBoss が
findAll
に対して 1 つのクエリを、また、見つかった各要素にアクセスするのに 1 つのクエリを実行するため、過剰な数のクエリが実行されます。この動作の原因は、JBoss コンテナ内でのクエリ結果の処理方法と関係があります。クエリが実行されると、選択された実際のエンティティ bean が返されるように見えますが、JBoss は実際は一致するエンティティのプライマリキーを戻すだけで、そのエンティティに対してメソッドが呼び出されるまで、エンティティをロードしません。これは n+1 問題として知られ、以降のセクションで説明する read-ahead ストラテジで対処します。
2 つ目の問題は、未使用フィールドの値が不必要にロードされることです。JBoss は
hangout
および organization
フィールドをロードしますが、これはアクセスされることはありません。(分かりやすくするために、複雑な contactInfo
フィールドを無効にしてあります)。
次の表でクエリを実行したものを示しています。
表30.1 非最適化クエリ実行
id | name | nick_name | badness | hangout | organization |
---|---|---|---|---|---|
0 | Yojimbo | Bodyguard | 7 | 0 | Yakuza |
1 | Takeshi | Master | 10 | 1 | Yakuza |
2 | Yuriko | Four finger | 4 | 2 | Yakuza |
3 | Chow | Killer | 9 | 3 | Triads |
4 | Shogi | Lightning | 8 | 4 | Triads |
5 | Valentino | Pizza-Face | 4 | 5 | Mafia |
6 | Toni | Toothless | 2 | 6 | Mafia |
7 | Corleone | Godfather | 6 | 7 | Mafia |