11.8. パフォーマンスチューニング
11.8.1. 代替のバッチローディングアルゴリズム リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
Hibernate では、4 つのフェッチングストラテジー (join、select、subselect、および batch) のいずれかを使用してアソシエーションのデータをロードできます。batch ローディングは select フェッチングの最適化ストラテジーであるため、パフォーマンスを最大限に向上できます。このストラテジーでは、主キーまたは外部キーのリストを指定することで、Hibernate が単一の SELECT ステートメントでエンティティーインスタンスまたはコレクションのバッチを読み出します。batch フェッチングは、レイジー select フェッチングストラテジーの最適化です。
batch フェッチングを設定する方法には、クラスごとのレベルと、コレクションごとのレベルの 2 つの方法があります。
- クラスごとのレベルHibernate がクラスごとのレベルでデータをロードする場合、クエリー時に事前ロードするアソシエーションのバッチサイズが必要になります。たとえば、起動時に
car
オブジェクトの 30 個のインスタンスがセッションでロードされるとします。各car
オブジェクトはowner
オブジェクトに属します。lazy
ローディングで、すべてのcar
オブジェクトを繰り返し、これらの owner (所有者) を要求する場合、Hibernate は owner ごとに 1 つ、合計 30 個の select ステートメントを発行します。これは、パフォーマンス上のボトルネックになります。この代わりに、クエリーによって要求される前に次の owner のバッチに対してデータを事前ロードするよう Hibernate を指示できます。owner
オブジェクトがクエリーされると、Hibernate は同じ SELECT ステートメントでこれらのオブジェクトをさらに多くクエリーします。事前にクエリーされるowner
オブジェクトの数は、設定時に指定されたbatch-size
パラメーターによって異なります。<class name="owner" batch-size="10"></class>
<class name="owner" batch-size="10"></class>
Copy to Clipboard Copied! Toggle word wrap Toggle overflow これは、今後必要になると見込まれる最低 10 個のowner
オブジェクトをクエリーするよう Hibernate に指示します。ユーザーがcar A
のowner
をクエリーする時、car B
のowner
はすでにバッチローディングの一部としてロードされた可能性があります。実際にcar B
のowner
が必要になった場合、データーベースにアクセスして SELECT ステートメントを発行する代わりに、現在のセッションより値を読み出すことができます。Hibernate 4.2.0 には、batch-size
パラメーターの他に、バッチローディングのパフォーマンスを向上する新しい設定項目が追加されました。この設定項目はBatch Fetch Style
設定と呼ばれ、hibernate.batch_fetch_style
パラメーターによって指定されます。LEGACY、PADDED、および DYNAMIC の 3 つのバッチフェッチスタイルがサポートされます。使用するスタイルを指定するには、org.hibernate.cfg.AvailableSettings#BATCH_FETCH_STYLE
を使用します。- LEGACY: LEGACY スタイルのローディングでは、
ArrayHelper.getBatchSizes(int)
を基にする事前ビルドされたバッチサイズが使用されます。既存のバッチ可能な識別子の数より、次に小さい事前ビルドされたバッチサイズを使用してバッチがロードされます。前述の例を用いた場合、batch-size
の設定が 30 であると、事前ビルドされたバッチサイズは [30, 15, 10, 9, 8, 7, .., 1] になります。29 個の識別子をバッチロードしようとすると、バッチは 15、10、および 4 になります。対応する 3 つの SQL クエリーが発生し、各クエリーはデータベースより 15、10、および 4 人の owner をロードします。 - PADDED - PADDED は LEGACY スタイルのバッチローディングと似ています。PADDED も事前ビルドされたバッチサイズを使用しますが、次に大きなバッチサイズを使用し、余分な識別子プレースホルダーを埋め込みます。上記の例で、30 個の owner オブジェクトが初期化される場合は、データベースに対して 1 つのクエリーのみが実行されます。29 個の owner オブジェクトが初期化される場合、Hibernate は同様にバッチサイズが 30 の SQL select ステートメントを 1 つ実行しますが、余分なスペースが繰り替えされる識別子で埋め込みされます。
- DYNAMIC - DYNAMIC スタイルのバッチローディングはバッチサイズの制限に準拠しますが、実際にロードされるオブジェクトの数を使用して SQL SELECT ステートメントを動的にビルドします。たとえば、30 個の owner オブジェクトで最大バッチサイズが 30 の場合、 30 個の owner オブジェクトの読み出しは 1 つの SQL SELECT ステートメントによって実行されます。35 個の owner オブジェクトの読み出す場合は、SQL ステートメントが 2 つになり、それぞれのバッチサイズが 30 と 5 になります。Hibernate は、制限どおりにバッチサイズを 30 以下とし、2 つ目の SQL ステートメントを動的に変更して、必要数である 5 にします。PADDED とは異なり、2 つ目の SQL は埋め込みされません。また、2 つ目の SQL ステートメントは動的に作成され、固定サイズでないことが LEGACY とは異なります。30 個未満のクエリーでは、このスタイルは要求された識別子の数のみを動的にロードします。
- コレクションごとのレベルHibernate は、前項の「クラスごとのレベル」で説明したバッチフェッチサイズとスタイルを維持してコレクションをバッチロードすることもできます。前項の例を逆にして、各
owner
オブジェクトによって所有されるすべてのcar
オブジェクトをロード必要があるとします。10 個のowner
オブジェクトがすべての owner を繰り返し、現セッションにロードされた場合、getCars()
メソッドの呼び出しごとに 1 つの SELECT ステートメントが生成されるため、合計で 10 個の SELECT ステートメントが生成されます。owner のマッピングでの car コレクションのバッチフェッチングを有効にすると、Hibernate は下記のようにこれらのコレクションを事前フェッチできます。<class name="Owner"><set name="cars" batch-size="5"></set></class>
<class name="Owner"><set name="cars" batch-size="5"></set></class>
Copy to Clipboard Copied! Toggle word wrap Toggle overflow よって、batch-size
が 5 で LEGACY バッチスタイルを使用する場合、Hibernate は 2 つの SELECT ステートメントの 5 つのコレクションをロードします。