0

私はSpring 2.5とそれに付随するHibernateを使用しています。Oracle 11g データベースに対して実行しています。

HibernateTemplate を拡張する DAO を作成しました。ここで、person テーブルに 500 万行を挿入するローダーを書きたいと思います。これは、CSV ファイルから行を読み取り、それを人に変換し、テーブルに保存するなど、単純な方法で記述しました。CSV ファイルが空になるまでこれを続けます。

問題は、約 450000 行でヒープ領域が不足していることです。そのため、メモリのサイズを 1024m から 2048m に 2 倍にすると、約 900000 行でメモリが不足します。

うーん....

そのため、Hibernate のクエリ キャッシュをオフにすることについていくつか読んだことがありますが、L2 キャッシュを使用していないため、これは問題ではないと思います。

JDBC2 のバッチ処理についていくつか読んだことがありますが、休止状態には当てはまらないと思います。

だから、私が見逃しているHibernateについての基本的なことがあるのだろうかと思っています。

4

3 に答える 3

2

正直なところ、私はそのために休止状態を使用していません。ORM は、何百万もの行を DB にロードするようには設計されていません。できないと言っているわけではありませんが、電気ドリルでプールを掘るようなものです。ドリルではなく、掘削機を使用します。

あなたの場合、データベースに付属のローダーアプリケーションを使用して、CSV を DB に直接ロードします。それをしたくない場合は、はい、バッチ挿入の方が効率的です。ただし、Hibernate で簡単にできるとは思いません。私があなただったら、プレーンな JDBC を使用するか、せいぜい Spring JDBC を使用します。

エンティティに複雑なビジネス ロジックがあり、絶対に Hibernate を使用する必要がある場合は、Richard が提案するように N レコードごとにフラッシュできます。ただし、それはかなり悪いハックだと思います。

于 2013-07-26T23:02:52.940 に答える
0

一次キャッシュ (Hibernate セッション) が原因で容量が不足しているようです。Hibernate セッションを定期的にフラッシュしてメモリ使用量を抑え、データベースのトランザクション ログが大きくなりすぎないように、数千行ごとにコミットすることで作業をチャンクに分割できます。

しかし、JDBC が遅いため、そのようなロード タスクに Hibernate を使用すると遅くなります。環境がどのようなものになるかをよく知っていて、データ量に上限があり、処理に十分な大きさのウィンドウがある場合は、管理できますが、複数で動作させたい状況ではさまざまなクライアント サイトがあり、一部のクライアント サイトのロード ジョブが機能しないために問題を解決するのにかかる時間を最小限に抑えたい場合は、データベースの一括コピー ツールを使用する必要があります。

バルク コピー アプローチは、データベースがすべての制約チェック、インデックス構築、およびトランザクション ログを一時停止することを意味し、代わりにデータを可能な限り高速に丸呑みすることに集中します。JDBC はデータベースからこのレベルの協力を得られないため、競合することはできません。以前のジョブでは、実行に 8 時間以上かかった JDBC ローダー タスクを、20 分かかった SQLLoader タスクに置き換えました。

データベースの独立性を犠牲にしますが、すべてのデータベースには一括コピー ツールがあります (DBA はそれらに依存しているため)。そのため、呼び出す exe とファイル形式の指定方法のみを変更する必要があり、データベースごとに非常に類似したプロセスが必要になります。このようにして、処理ウィンドウを最大限に活用できます。

于 2013-08-06T14:55:23.530 に答える