Spring / Hibernateを使用した一括挿入
-
10-07-2019 - |
質問
アプリケーションでSpring / Hibernateのミックスを使用しています(オリジナルはありません)。特定の機能について、CSVファイルの内容をOracle DBのテーブルにインポートする必要があります。 今のところ、私はオブジェクトを作成するだけです、私はします
HibernateTemplate.saveOrUpdate
それぞれについて(新しく割り当てられたIDを取得する必要があります)
次に、SpringトランザクションAPIを使用して、メソッドの最後にトランザクションが発生します。
パフォーマンスを除き、すべてが正常に機能します。パフォーマンスは、約5000のオブジェクトに対しては正しいですが、100 000に対しては正しくありません...
だから、私はこのようなことを加速するためのアイデアを探しています。 Hibernateでの一括挿入について聞いたことがありますが、確実な参照は見つかりませんでした。誰でもこのインポートをより高いパフォーマンスで実行するためのアイデアを教えてもらえますか?
解決
簡単にできることは、100個のオブジェクトごとにセッションをフラッシュしてクリアすることです...
so execute
session.flush();
session.clear();
100または1000ごとの挿入。
これにより、休止状態のセッションがフラッシュされてクリアされ、セッションが大きくなりすぎるのが停止します(おそらく、100,000個のオブジェクトに時間がかかっている理由)。
さらに、ID識別子ジェネレーターを使用している場合、hibernateはサイレントモードでバッチ挿入をオフにします。バッチ挿入によりパフォーマンスが向上します。また、一度に100に相当するhibernate.jdbc.batch_size構成プロパティを指定する必要があります。
ManningのHibernateでのJava Persistenceがこのソースでした(素晴らしい本-私の肌を何度も救いました)。
他のヒント
StatelessSession 一括操作用に設計されているため。
StatelessSession ss=sessionFactory().openStatelessSession();
Transaction tx=ss.beginTransaction();
ORMapperが釘の正しいハンマーではない場合があります。特に、バッチ操作は、多くの場合、従来のJDBCを使用してより効率的に実行されます。もちろん、これはさまざまな条件に依存しますが、少なくともオプションとしてこれを見て、両方のアプローチのパフォーマンスを比較する必要があります。
これは、純粋にデータベース挿入のパフォーマンスの問題ではありません。フラッシュを実行せずに何万ものオブジェクトを作成している場合、Hibernateセッションはメモリがなくなるまで成長します。