構成で JDBC batch_size 値を指定する使用と、永続コンテキストのフラッシュ/クリアを手動で制御する使用は、2 つの独立した戦略であり、非常に異なる目的を果たします。
flush()
とペアで使用する主な目的はclear()
、生徒の記録を保存するときに PersistenceContext によって使用される Java アプリケーション側のメモリ消費を最小限に抑えることです。例が示すようにステートフルを使用している場合Session
、Hibernate はエンティティの添付/管理されたコピーをメモリ内に維持することを覚えておくことが重要です。したがって、メモリ不足を避けるために、定期的にこれをクリアしてデータベースにフラッシュすることが重要です。またはパフォーマンスに影響を与えます。
JDBC の batch_size 設定自体は、パフォーマンスを向上させるために実際のドライバーがステートメントをデータベースにフラッシュする頻度に影響します。少し変更した例を見てみましょう。
Session session = sessionFactory.openSession();
try {
session.getTransaction().begin();
for ( int i = 0; i < 10000; ++i ) {
Student student = new Student();
...
session.save( student );
}
session.getTransaction().commit();
}
catch( Throwable t ) {
if ( session.getTransaction().getStatus() == TransactionStatus.ACTIVE ) {
session.getTransaction().rollback();
}
throw t;
}
finally {
session.close();
}
ご覧のとおり、ここではflush()
orを使用していませんclear()
。
ここで何が起こるかというと、Hibernate はコミット時にフラッシュを実行するため、ドライバーはデータベースに個別にではなく、batch_size の数の挿入を一括で送信します。したがって、10,000 個のネットワーク パケットが送信されるのではなく、batch_size が 250 の場合、40 個のパケットしか送信されません。
ここで重要なのは、やなどの ID ベースの識別子を使用するなど、バッチ処理を無効にする要因があることです。なんで?IDENTITY
AUTO_INCREMENT
これは、Hibernate がエンティティを PersistenceContext に格納するには、エンティティの ID を知る必要があり、IDENTITY
ベースの識別子生成を使用するときにその値を取得する唯一の方法は、各挿入操作の後に実際にデータベースに値をクエリすることであるためです。したがって、挿入をバッチ処理することはできません。
これこそまさに、一括挿入操作を行っている人が、選択した識別子生成戦略が与える影響を認識していないため、パフォーマンスの低下を観察することが多い理由です。
バッチの読み込みを最適化する場合は、代わりに、キャッシュされたシーケンス ジェネレーターまたは手動でアプリケーションに割り当てられた識別子を使用することをお勧めします。
とを使用した例に戻るflush()
とclear()
、同じ問題が識別子生成戦略にも当てはまります。これらの操作をデータベースに一括/バッチで送信する場合は、 に使用している識別子戦略に注意してくださいStudent
。