CSVファイルを処理し、各レコード(行)ごとにエンティティを保持する必要があります。今、私はこのようにしています:
_while ((line = reader.readNext()) != null) {
Entity entity = createEntityObject(line);
entityManager.save(entity);
i++;
}
_
ここで、save(Entity)
メソッドは基本的に単なるEntityManager.merge()
呼び出しです。 CSVファイルには約20,000のエンティティ(行)があります。これは効果的な方法ですか?かなり遅いようです。 EntityManager.persist()
を使用する方が良いでしょうか?このソリューションには何らかの欠陥がありますか?
[〜#〜]編集[〜#〜]
これは長いプロセス(400秒以上)であり、persist
とmerge
を使用して両方のソリューションを試しました。どちらも、完了するまでにほぼ同じ時間がかかります(459秒と443秒)。問題は、このようにエンティティを1つずつ保存することが最適かどうかです。私の知る限り、Hibernate(これは私のJPAプロバイダーです)はキャッシュ/フラッシュ機能を実装しているので、これについて心配する必要はありません。
JPA APIは、これを最適化するためのすべてのオプションを提供しているわけではありません。これをどれだけ速く実行したいかに応じて、ORM固有のオプション(ケースではHibernate)を探す必要があります。
確認すること:
したがって、Ebean ORMでは次のようになります。
EbeanServer server = Ebean.getServer(null);
Transaction transaction = server.beginTransaction();
try {
// Use JDBC batch API with a batch size of 100
transaction.setBatchSize(100);
// Don't bother getting generated keys
transaction.setBatchGetGeneratedKeys(false);
// Skip cascading persist
transaction.setPersistCascade(false);
// persist your beans ...
Iterator<YourEntity> it = null; // obviously should not be null
while (it.hasNext()) {
YourEntity yourEntity = it.next();
server.save(yourEntity);
}
transaction.commit();
} finally {
transaction.end();
}
そして、JDBCを介してこれを行う場合は、ORMオーバーヘッド(オブジェクトの作成やガベージコレクションなどが少ない)をスキップします。そのため、このオプションは無視しません。
はい、これはあなたの質問には答えませんが、より多くのORM固有のバッチ挿入の微調整の検索に役立つ可能性があります。
これを行う一般的な方法の1つは、トランザクションを使用することです。新しいトランザクションを開始してから多数のオブジェクトを永続化する場合、トランザクションをコミットするまで、それらのオブジェクトは実際にはDBに挿入されません。コミットするアイテムの数が多い場合、これはいくつかの効率を上げることができます。
チェックアウト EntityManager.getTransaction
少なくともHibernateではそれをより高速にするために、特定の数の挿入の後にflush()およびclear()を実行します。私は何百万ものレコードに対してこのアプローチを実行しましたが、うまくいきます。まだ遅いですが、やらないよりずっと速いです。基本的な構造は次のとおりです。
int i = 0;
for(MyThingy thingy : lotsOfThingies) {
dao.save(thingy.toModel())
if(++i % 20 == 0) {
dao.flushAndClear();
}
}
古典的なSQL挿入ステートメントを使用して、データベースに直接書き込むことができます。