第14章バッチ処理(Batch processing)
第14章バッチ処理(Batch processing)
Hibernateを使用して100,000件のレコードをデータベースに挿入するのは自然な方法かもしれません.
このプログラムは約50,000件のレコードを実行すると失敗し、メモリオーバーフロー異常(OutOfMemoryException)が放出されます.これは、Hibernateが新しく挿入したすべてのクライアントインスタンスをsessionレベルのキャッシュ領域でキャッシュしたためです.
この章では、このような問題を回避する方法を説明します.まず、バッチ処理を実行し、理想的なパフォーマンスを達成するには、JDBCのバッチ機能を使用することが重要です.JDBCのバッチ・キャプチャ数(batch size)パラメータを適切な値(例えば、10-50の間)に設定します.
バッチ処理を実行するときに2次キャッシュを閉じることもできます.
14.1.バッチ挿入(Batch inserts)
多くのオブジェクトを永続化するには、flush()を頻繁に呼び出し、clear()を後で呼び出すことで、第1レベルのキャッシュのサイズを制御する必要があります.
14.2.一括更新(Batch updates)
この方法は、データの取得と更新にも適用されます.また、多くのロー・データを返すクエリーを行う場合は、scroll()メソッドを使用して、サーバ側カーソルのメリットを十分に活用する必要があります.
14.3.大量更新/削除(Bulk update/delete)
既に説明したように、自動および透明なオブジェクト/リレーションシップマッピング(object/relational mapping)は、管理オブジェクトのステータスに注目します.これは、オブジェクトのステータスがメモリに存在することを意味します.したがって、(SQL文UPDATEおよびDELETEを使用して)データベース内のデータを直接更新または削除しても、メモリ内のオブジェクトステータスおよびオブジェクトデータには影響しません.ただし、Hibernateは、Hibernateクエリ言語(第15章HQL:Hibernateクエリ言語)によって大量のSQLスタイルの(UPDATE)文と(DELETE)文を実行する方法を提供する.
UPDATE文とDELETE文の構文は、(UPDATE|DELETE)FROM?ClassName (WHERE WHERE_CONDITIONS)?. いくつかの説明があります. FROM句(from-clause)では、FROMキーワードはオプションの である. FROM句(from-clause)にはクラス名が1つしかなく、別名 はありません.大量のHQL文では接続を使用できません(明示的または暗黙的には使用できません).ただし、WHERE句ではサブクエリを使用できます. WHERE句全体がオプションです.
例を挙げるとQuery.ExcuteUpdate()メソッドは、HQL UPDATE文を実行します.
同様にQQueryを使用するHQL DELETEを実行します.ExcuteUpdate()メソッド(JDBC PreparedStatement.executeUpdate()に詳しい人のために設定されています)
Query.executeUpdate()メソッドで返される整数値は、この操作の影響を受けるレコードの数を示します.この値は、データベース内の(最後のSQL文)によって影響された「行」と一致する可能性があります.数に関係していますが、ないかもしれません.大量のHQL操作は、joined-subclassマッピング方式のクラスに対するこのような操作を例に挙げると、複数の実際のSQL文が実行される可能性があります.この戻り値は、実際に文によって影響されたレコードの数を表します.そのjoined-subclassの例では、1つのサブクラスの削除は、実際にはサブクラスがマッピングしたテーブルだけでなく、「ルート」テーブルにも影響し、継承関係のあるjoined-subclassマッピング方式のサブクラスのテーブルにも影響する可能性があります.
なお、上記の大量のHQL操作の少数の制限は、新しいバージョンで改善される.さらに詳しくはJIRAの路線図(roadmap)を参照してください.
原文住所:http://oss.org.cn/ossdocs/framework/hibernate/reference-v3_zh-cn/batch.html
Hibernateを使用して100,000件のレコードをデータベースに挿入するのは自然な方法かもしれません.
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
}
tx.commit();
session.close();
このプログラムは約50,000件のレコードを実行すると失敗し、メモリオーバーフロー異常(OutOfMemoryException)が放出されます.これは、Hibernateが新しく挿入したすべてのクライアントインスタンスをsessionレベルのキャッシュ領域でキャッシュしたためです.
この章では、このような問題を回避する方法を説明します.まず、バッチ処理を実行し、理想的なパフォーマンスを達成するには、JDBCのバッチ機能を使用することが重要です.JDBCのバッチ・キャプチャ数(batch size)パラメータを適切な値(例えば、10-50の間)に設定します.
hibernate.jdbc.batch_size 20
バッチ処理を実行するときに2次キャッシュを閉じることもできます.
hibernate.cache.use_second_level_cache false
14.1.バッチ挿入(Batch inserts)
多くのオブジェクトを永続化するには、flush()を頻繁に呼び出し、clear()を後で呼び出すことで、第1レベルのキャッシュのサイズを制御する必要があります.
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) { //20, same as the JDBC batch size //20, JDBC
//flush a batch of inserts and release memory:
//
session.flush();
session.clear();
}
}
tx.commit();
session.close();
14.2.一括更新(Batch updates)
この方法は、データの取得と更新にも適用されます.また、多くのロー・データを返すクエリーを行う場合は、scroll()メソッドを使用して、サーバ側カーソルのメリットを十分に活用する必要があります.
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
ScrollableResults customers = session.getNamedQuery("GetCustomers")
.setCacheMode(CacheMode.IGNORE)
.scroll(ScrollMode.FORWARD_ONLY);
int count=0;
while ( customers.next() ) {
Customer customer = (Customer) customers.get(0);
customer.updateStuff(...);
if ( ++count % 20 == 0 ) {
//flush a batch of updates and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
14.3.大量更新/削除(Bulk update/delete)
既に説明したように、自動および透明なオブジェクト/リレーションシップマッピング(object/relational mapping)は、管理オブジェクトのステータスに注目します.これは、オブジェクトのステータスがメモリに存在することを意味します.したがって、(SQL文UPDATEおよびDELETEを使用して)データベース内のデータを直接更新または削除しても、メモリ内のオブジェクトステータスおよびオブジェクトデータには影響しません.ただし、Hibernateは、Hibernateクエリ言語(第15章HQL:Hibernateクエリ言語)によって大量のSQLスタイルの(UPDATE)文と(DELETE)文を実行する方法を提供する.
UPDATE文とDELETE文の構文は、(UPDATE|DELETE)FROM?ClassName (WHERE WHERE_CONDITIONS)?. いくつかの説明があります.
例を挙げるとQuery.ExcuteUpdate()メソッドは、HQL UPDATE文を実行します.
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlUpdate = "update Customer set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
.setString( "newName", newName )
.setString( "oldName", oldName )
.executeUpdate();
tx.commit();
session.close();
同様にQQueryを使用するHQL DELETEを実行します.ExcuteUpdate()メソッド(JDBC PreparedStatement.executeUpdate()に詳しい人のために設定されています)
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlDelete = "delete Customer where name = :oldName";
int deletedEntities = s.createQuery( hqlDelete )
.setString( "oldName", oldName )
.executeUpdate();
tx.commit();
session.close();
Query.executeUpdate()メソッドで返される整数値は、この操作の影響を受けるレコードの数を示します.この値は、データベース内の(最後のSQL文)によって影響された「行」と一致する可能性があります.数に関係していますが、ないかもしれません.大量のHQL操作は、joined-subclassマッピング方式のクラスに対するこのような操作を例に挙げると、複数の実際のSQL文が実行される可能性があります.この戻り値は、実際に文によって影響されたレコードの数を表します.そのjoined-subclassの例では、1つのサブクラスの削除は、実際にはサブクラスがマッピングしたテーブルだけでなく、「ルート」テーブルにも影響し、継承関係のあるjoined-subclassマッピング方式のサブクラスのテーブルにも影響する可能性があります.
なお、上記の大量のHQL操作の少数の制限は、新しいバージョンで改善される.さらに詳しくはJIRAの路線図(roadmap)を参照してください.
原文住所:http://oss.org.cn/ossdocs/framework/hibernate/reference-v3_zh-cn/batch.html