11

次のような単純なHibernateクエリがあります。

from MyEntity where name = ?

特別なことは何もありませんが、かなり大きなトランザクションで何度も呼び出されます(1秒間続き、数十または数百のエンティティをロードする場合があります)。プロファイラーは、次のことに多くの時間が費やされていることを示しています。

org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1185)
org.hibernate.internal.SessionImpl.list(SessionImpl.java:1240)
org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)

つまり、実際のクエリを実行する前に変更をフラッシュします。

どういうわけか、Hibernateがこのフラッシュを実行するのを完全に防ぐことはできますか?

そうでない場合、それをより速くするために私は何ができますか?

4

2 に答える 2

18

デフォルトでは、Hibernateはセッション中にクエリを発行する前にフラッシュし(FlushMode.AUTO)、それを実行するために多くのCPU時間を消費します。多くのクエリと更新が交互に実行されるセッションがある場合は、特に苦痛になります。

現在のセッション中に挿入/更新/削除したデータをクエリが選択する可能性が高い場合は、これらのフラッシュが必要です。これ、現在のトランザクションで何も変更していないが、read-uncommittedなどのトランザクション分離レベルを使用している場合にも当てはまる可能性があります。

コミットされていない読み取りなどが必要ないと仮定すると、これを回避する方法は2つあります。

  1. 変更を加える前に、セッション中に必要なものをすべて選択します(つまり、変更を加える前にすべてのクエリが発行されるように並べ替えます)。
  2. このセッションで変更されていないデータを選択していることが確実にわかっている場合は、次のように、フラッシュモードをフラッシュをトリガーしないものに明示的に設定できます。

    Query query = session.getNamedQuery(SOME_QUERY_NAME);
    query.setFlushMode(FlushMode.COMMIT);
    
于 2013-01-22T08:30:29.567 に答える
-1

Hibernateはバージョン3.3でフラッシュロジックを変更しました。

FlushMode.MANUALこれで、に設定されている場合でも、ダーティエンティティが存在するテーブルにクエリを実行していることが検出されると、常にフラッシュされます。

私が考えることができるいくつかの回避策:

  • ダーティテーブルをクエリせず、設定FlushMode.COMMIT以下になるように操作を並べ替えます。
  • 変更する前にエンティティを切り離し、後で再接続して、Hibernateが変更されたことを認識しないようにします。
  • AutoFlushEventListener異なる振る舞いで習慣を提供します。それには低レベルのいじりが必要であり、何か他のものを壊す可能性があります。
于 2021-05-07T11:13:17.343 に答える