4

タスクを実行するために大量のデータを取得する必要があるjavajpa/hibernateアプリがあります。n + 1の問題が発生したため、hibernate.default_batch_fetch_size(@batchsize)プロパティを使用して、必要なSQLラウンドトリップを減らすことにしました。いくつかの値を試しましたが、ほとんどすべての値でパフォーマンスが低下しました。

バッチサイズ:0-SQL送信:14000-期間:約1分

バッチサイズ:4-SQL送信:5000-期間:10分以上

バッチサイズ:10-SQL送信:2700-期間:約5分

バッチサイズ:100-SQL送信:400-期間:約1分

これは「通常の」動作ですか?そうでない場合、何が間違いである可能性がありますか?

生成されたSQLをlog4jdbcでログに記録しました。私は、バッチ処理されたすべてのステートメントの間に約100〜150ミル秒あることに気づきました。後でSQLを実行すると、各ステートメントの実行時間は20ミリ秒以下でした。したがって、これはDB(INステートメント)関連の問題ではありません。

Java:1.6.0_31、Hibernate 3.6.7、DB Postgres 9.1.1、JDBC postgresql-9.1-901.jdbc4.jar

前もって感謝します

明確にするための更新:パフォーマンスの低下は、バッチ更新/挿入ではなく、バッチフェッチ中です。

4

1 に答える 1

5

いくつかのデバッグの後、私は問題を見つけました。Hibernate(少なくともバージョン3.6.7では)は、マップされたすべてのコレクションをマップに保管します。これらのマップには、次のようなスニペットでアクセスできます。

SessionImpl si = ((SessionImpl) entityManager.getDelegate());
PersistenceContext persistenceContext = si.getPersistenceContext();
persistenceContext.getCollectionEntries();

したがって、すべてのコレクションがこのマップに1つのエントリを作成します。私の場合のように、コレクションがたくさんあるpojoがある場合、これは急速に大きくなります。たとえば、32個のコレクションごとに10.000個のpojoがロードされ、320.000個のコレクションエントリがあります。Hibernateは、マップ(org.hibernate.engine.BatchFetchQueue.getCollectionBatch(CollectionPersister、Serializable、int、EntityMode))を反復処理して、ロードされていないコレクションIDを検索し、これらを後でIN句に配置するようになりました。Hibernateは、キーの検索を特定のタイプのコレクションに制限しないため、これはさらに悪化します。

私はいくつかのコレクションをクリーンアップする必要があると思います。休止状態がより高いバージョンのキーを見つけるためのより効率的な方法を取得することを願っています。

更新:休止状態のjiraに関するこのコメントは、同じ問題を抱えている人にとって興味深いかもしれません: https ://hibernate.onjira.com/browse/HHH-1775?focusedCommentId=42686&page=com.atlassian.jira.plugin.system.issuetabpanels:comment -tabpanel#comment-42686

更新:この問題はHibernateバージョンで修正されました:4.1.8

于 2012-06-04T14:23:31.180 に答える