13.8. パフォーマンスチューニング
13.8.1. 他のバッチロードアルゴリズム
Hibernate では、join、select、subselect、および batch の 4 つののフェッチストラテジーのいずれかを使用して関連付けのデータを読み込むことができます。これら 4 つのストラテジーにおいて、バッチローディングでは、select フェッチの最適化ストラテジーであるため、これらのストラテジーの外で、パフォーマンスを大幅に向上させることができます。このストラテジーでは、Hibernate はプライマリーキーまたは外部キーのリストを指定して、単一の SELECT ステートメントでエンティティーインスタンスまたはコレクションのバッチを取得します。batch フェッチは、レイジー select フェッチストラテジーの最適化です。
batch フェッチの設定方法は、クラス当たりのレベルまたはコレクション当たりのレベルです。
- クラス当たりのレベルHibernate がクラス当たりのレベルでデータを読み込む場合は、クエリーの実行時にロードする関連付けのバッチサイズが必要になります。たとえば、ランタイム時に、セッションに 30 個のインスタンスの
car
オブジェクトがロードされているとします。各car
オブジェクトはowner
オブジェクトに属します。すべてのcar
オブジェクトを繰り返し処理し、所有者を要求する場合、lazy
読み込みでは、Hibernate は所有者ごとに 30 個の select ステートメントを発行します。これはパフォーマンスのボトルネックです。代わりに、Hibernate に対して、クエリーを経由する前に所有者の次のバッチのデータを事前に読み込むように指示することもできます。owner
オブジェクトがクエリーされると、Hibernate は同じ SELECT ステートメントで多くのこれらのオブジェクトをクエリーします。事前にクエリーするowner
オブジェクトの数は、設定時に指定されたbatch-size
パラメーターによって異なります。<class name="owner" batch-size="10"></class>
これにより、Hibernate は、後で必要と予想される 10 個以上のowner
オブジェクトをクエリーするようになります。ユーザーがクエリーを実行するとowner
のcar A
、owner
のcar B
バッチロードの一部としてすでにロードされている可能性があります。ユーザーがデータベースに移動 (および SELECT ステートメントを実行) する代わりに、実際にcar B
のowner
が必要な場合は、現在のセッションから値を取得できます。batch-size
パラメーターに加えて、Hibernate 4.2.0 ではバッチロードのパフォーマンスを強化する新しい設定項目が導入されました。設定アイテムは呼び出されますBatch Fetch Style
設定であり、hibernate.batch_fetch_style
パラメーターで指定されます。LEGACY、PADDED、DYNAMIC といった異なるバッチフェッチスタイルがサポートされています。使用するスタイルを指定するには、org.hibernate.cfg.AvailableSettings#BATCH_FETCH_STYLE
。- レガシー: レガシースタイルの読み込みでは、に基づいて事前に作成されたバッチサイズのセット
ArrayHelper.getBatchSizes(int)
利用されます。バッチは、既存のバッチ可能な識別子の数からの次に小さな事前ビルドされたバッチサイズを使用してロードされます。上記の例を続けて、batch-size
30 に設定すると、事前に作成されたバッチサイズは 30、15、10、9、8、7、..、1 になります。ロード 29 識別子のバッチ処理を試みると、15、10、および 4 のバッチが発生します。対応する SQL クエリーは 3 つあり、各クエリーはデータベースから 15、10、および 4 の所有者 (owner) を読み込みます。 - PADDED - PADDED は、バッチローディングの LEGACY スタイルに似ています。依然として事前ビルドされたバッチサイズを使用していますが、次に大きなバッチサイズを使用し、追加の識別子プレースホルダーをパディングします。上記の例と同様に、30 個の owner オブジェクトを初期化する場合、データベースに対してクエリーが実行されるのは 1 つのみとなります。ただし、29 個の owner オブジェクトが初期化される場合でも、Hibernate は依然としてバッチサイズ 30 の SQL select ステートメントのみを実行し、識別子が連続する追加スペースがパディングされます。
- Dynamic - バッチサイズの制限に準拠していますが、このスタイルのバッチロードは、実際に読み込まれるオブジェクト数を使用して SQL SELECT ステートメントを動的に構築します。たとえば、owner オブジェクトが 30 個で、最大バッチサイズが 30 の場合、30 個の owner オブジェクトを取得する呼び出しは、1 つの SQL SELECT ステートメントになります。35 個を取得する呼び出しは、バッチサイズ 30 と 5 の 2 つの SQL ステートメントになります。Hibernate は、必要な数である 5 を維持するために 第 2 の SQL ステートメントを動的に変更します。また、バッチサイズは制限の 30 のままに保持します。これは、PADDED バージョンとは異なります。第 2 の SQL は PADDED されません。LEGACY スタイルとは異なり、第 2 の SQL ステートメントには固定サイズがなく、次の SQL は動的に作成されます。クエリーが 30 個の識別子を下回る場合、このスタイルは要求された識別子の数のみを動的に読み込みます。
- コレクション当たりのレベルHibernate では、上記の各クラス当たりのセクションにリストされているバッチフェッチサイズとスタイルを採用するロードコレクションのバッチ処理も可能です。前のセクションで使用した例を戻すには、各
owner
オブジェクトが所有するすべてのcar
オブジェクトをロードする必要があることを考慮してください。10 個のowner
オブジェクトが現行セッションでロードされ、すべての owner で 反復すると、10 個の SELECT ステートメントが生成されます (getCars()
メソッドへの呼び出しごと)。Owner のマッピングで cars コレクションのバッチフェッチを有効にすると、Hibernate は以下のようにこれらのコレクションの事前フェッチを実行できます。<class name="Owner"><set name="cars" batch-size="5"></set></class>
したがって、バッチサイズが 5 で、レガシーバッチスタイルを使用して 10 のコレクションをロードする場合、Hibernate は 2 つの SELECT ステートメントを実行し、それぞれが 5 のコレクションを取得することになります。