ホームページ > バックエンド開発 > C#.Net チュートリアル > 休止状態キャッシュの問題については、次のとおりです。

休止状態キャッシュの問題については、次のとおりです。

巴扎黑
リリース: 2016-12-20 14:19:27
オリジナル
1067 人が閲覧しました

1. Hibernate キャッシュについて:
1.1.1. 基本的なキャッシュ原理
Hibernate キャッシュは 2 つのレベルに分かれており、最初のレベルはデフォルトで提供されており、アンインストールすることはできません。

2 番目のレベルは、sessionFactory によって制御されるプロセスレベルのキャッシュです。これはグローバルに共有されるキャッシュであり、2 次キャッシュを呼び出すクエリ メソッドはすべてそのメリットを享受できます。 2 次キャッシュは、正しく構成されている場合にのみ機能します。同時に、条件付きクエリを実行するときに、対応するメソッドを使用してキャッシュからデータを取得する必要があります。たとえば、Query.iterate() メソッド、load、get メソッドなどです。 session.find メソッドは常にデータベースからデータを取得し、必要なデータが含まれている場合でも 2 次キャッシュからはデータを取得しないことに注意してください。

クエリ時にキャッシュを使用する実装プロセスは次のとおりです。まず、必要なデータが 1 次キャッシュにあるかどうかをクエリします。ない場合は、2 次キャッシュにクエリを実行します。データベース。これら 3 つの方法のクエリ速度は順番に低下することに注意してください。
1.2. 既存の問題
1.2.1. 一次キャッシュの問題と二次キャッシュを使用する理由
セッションの有効期間は非常に短いことが多いため、存在する最も高速な一次キャッシュの有効期間はセッション内も非常に短いため、一次キャッシュのヒット率は非常に低くなります。システムパフォーマンスの向上も非常に限られています。もちろん、このセッション内部キャッシュの主な機能は、セッションの内部データ状態の同期を維持することです。これは、システム パフォーマンスを大幅に向上させるために休止状態によって提供されるものではありません。
Hibernate を使用したパフォーマンスを向上させるには、次のような注意が必要な従来の方法に加えて、
遅延読み込み、緊急の外部接続、クエリ フィルタリングなどの使用、Hibernate の 2 次キャッシュを構成する必要もあります。システム全体のパフォーマンスの向上は、多くの場合すぐに結果をもたらします。
(以前のプロジェクトでの経験から、一般に 3 ~ 4 倍のパフォーマンス向上が見られます)

1.2.2. N+1 クエリの問題
条件付きクエリを実行するとき、 iterate() メソッドには有名な「n+」があります。 1" クエリの問題、つまり最初のクエリでは、反復メソッドは条件を満たすクエリ結果の数に 1 つ (n+1) のクエリを加えた数を実行します。ただし、この問題は最初のクエリ中にのみ存在し、後で同じクエリを実行するとパフォーマンスが大幅に向上します。この方法は、大量のデータを含むビジネス データのクエリに適しています。
ただし、注意: データ量が特に大きい場合 (パイプライン データなど)、キャッシュ内に存在するレコードの最大数を設定するなど、この永続オブジェクトに固有のキャッシュ戦略を構成する必要があります。キャッシュの存在時間とその他の回避すべきパラメータ システムは同時に大量のデータをメモリにロードするため、メモリ リソースが急速に枯渇し、結果的にシステム パフォーマンスが低下します。 ! !

1.3. Hibernate の 2 次キャッシュを使用する場合のその他の考慮事項:
1.3.1. データの有効性について
さらに、Hibernate はキャッシュ内のデータを確実に 2 次キャッシュに保持します。データベース内の実際のデータは一貫性があります。 save()、update()、または saveOrUpdate() メソッドを呼び出してオブジェクトを渡すとき、またはload()、get()、list()、iterate()、またはscroll()メソッドを使用してオブジェクトを取得するときは常に、オブジェクトはセッションの内部キャッシュに追加されます。 その後、flush() メソッドが呼び出されると、オブジェクトの状態がデータベースと同期されます。

つまり、データの削除、更新、追加を行うと、同時にキャッシュも更新されます。もちろん、これには L2 キャッシュも含まれます。

データベース関連の作業を実行するために休止状態 API が呼び出される限り。 Hibernate はキャッシュされたデータの有効性を自動的に保証します。 !

ただし、JDBC を使用して休止状態をバイパスし、データベースに対して直接操作を実行する場合。現時点では、Hibernate はデータベースに加えられた変更をそれ自身で感知しないか、感知することができず、キャッシュ内のデータの有効性を保証できなくなります。 !

これもすべての ORM 製品に共通する問題です。幸いなことに、Hibernate はキャッシュ クリア メソッドを公開しているため、データの有効性を手動で確認する機会が得られます。 !
一次キャッシュと二次キャッシュには対応するクリア方法があります。二次キャッシュによって提供される削除方法は次のとおりです。
オブジェクト CLASS を押してキャッシュを空にします。
オブジェクト CLASS とオブジェクトの主キー ID を押して、オブジェクトのオブジェクトのセット内のキャッシュ データをクリアします。

1.3.2. 使用に適した状況
すべての状況が 2 次キャッシュの使用に適しているわけではなく、特定の状況に応じて決定する必要があります。同時に、永続オブジェクトに対して特定のキャッシュ戦略を構成できます。

2 次キャッシュが使用される状況に適しています。
1. データはサードパーティによって変更されません。

一般に、変更されるデータに対しては 2 次キャッシュを設定しないことをお勧めします。データの不整合の発生を避けるため、休止状態以外の機能を使用します。ただし、パフォーマンス上の理由からこのデータをキャッシュする必要があり、SQL などのサードパーティによって変更される可能性がある場合は、そのデータ用に 2 次キャッシュを構成することもできます。ただ、現時点では SQL を変更した後にキャッシュクリアメソッドを手動で呼び出す必要があります。データの一貫性を確保するため

2. データ サイズが許容範囲内である

データ テーブル内のデータ量が特に大きい場合、現時点では 2 次キャッシュには適していません。その理由は、キャッシュされたデータが多すぎるとメモリ リソースの制約が発生し、パフォーマンスが低下する可能性があるためです。

データテーブル内のデータ量が特に大きい場合、データの新しい部分のみが使用されることがよくあります。現時点では、2 次キャッシュを構成することもできます。ただし、永続クラスのキャッシュ戦略 (キャッシュの最大数、キャッシュの有効期限など) は個別に設定する必要があり、これらのパラメータは妥当な範囲に減らす必要があります (高すぎるとメモリ リソースの制約が発生し、低すぎると、キャッシュはほとんど意味を持ちません)。

3. データの更新頻度が低いです。

データの更新頻度が高すぎるデータの場合、キャッシュ内のデータを頻繁に同期するコストは、キャッシュ内のデータをクエリすることで得られるメリットと同等になる可能性があります。そして利益は相殺されます。現時点では、キャッシュはあまり重要ではありません。


4. 非重要データ(財務データ等ではない)

財務データ等は非常に重要なデータであり、無効なデータの掲載や使用は絶対に認められませんので、使用しない方が良いでしょう。現時点ではセキュリティ上の理由から 2 次キャッシュが使用されていません。
現時点では、「高性能」の重要性よりも「正しさ」の重要性の方がはるかに大きいからです。

2. 現在のシステムで休止状態キャッシュを使用する場合の推奨事項
1.4. 現状
一般的なシステムでは、データベース操作を実行するために休止状態をバイパスする状況が 3 つあります。

1. 複数のアプリケーション システムが同時にデータベースにアクセスする場合
この場合、hibernate 2次キャッシュを使用すると必然的にデータの不整合が発生します
この時、詳細な設計が必要です。たとえば、設計では同じデータ テーブルへの同時書き込み操作を避け、データベースでさまざまなレベルのロック メカニズムを使用します。

2. 動的テーブル関連

いわゆる「動的テーブル」とは、システムの実行時にユーザーのオペレーティング システムに応じて自動的に作成されるデータ テーブルを指します。

たとえば、「カスタム フォーム」やユーザー定義の拡張機能開発の性質に属するその他の機能モジュールでは、データ テーブルが実行時に作成されるため、Hibernate マッピングを実行できません。したがって、それに対する操作は、休止状態をバイパスする直接データベース JDBC 操作のみにすることができます。

この時点で動的テーブル内のデータがキャッシュされていない場合、データの不整合の問題は発生しません。

現時点で独自のキャッシュ メカニズムを設計する場合は、独自のキャッシュ同期メソッドを呼び出すだけです。对3. SQL を使用して Hibernate 永続オブジェクト テーブルを一括削除する場合、この時点で一括削除を実行すると、キャッシュ内に削除されたデータが残ります。

分析:

記事 3 (SQL バッチ削除) が実行されると、後続のクエリは次の 3 つの方法のみになります:

a. session.find() メソッド:
前の概要によると、find メソッドはクエリを実行しません。 2 番目のクエリはキャッシュされたデータですが、データベースに直接クエリします。

したがって、データの有効性には問題はありません。

b. iterate メソッドを呼び出して条件付きクエリを実行する場合:
iterate クエリ メソッドの実行方法に従って、毎回条件を満たす ID 値をデータベースにクエリし、キャッシュからデータを取得します。この ID に基づいて、キャッシュにそのような ID が存在しない場合、データベース クエリでは ID のデータのみが実行されます。このレコードが SQL によって直接削除されている場合、反復処理は ID クエリの実行時に ID をクエリしません。 。したがって、このレコードがキャッシュ上に存在しても、顧客が取得することはなく、不整合は生じません。 (この状況はテストによって確認されています)

c. get メソッドまたは load メソッドを使用して、ID によってクエリを実行します:

客観的には、この時点で期限切れのデータがクエリされます。ただし、システム内の SQL 一括削除は通常、中間関連データ テーブルの場合は

であるため、
の場合は

中間関連付けテーブルのクエリは通常、条件付きクエリを使用します。ID によって特定の関連付け関係をクエリする可能性は非常に低いため、この問題は存在しません。

値オブジェクトが ID によって関連付け関係をクエリする必要がある場合は、同時にデータ量が多いため、SQL を使用して一括削除を実行します。これら 2 つの条件が満たされる場合、ID によるクエリで正しい結果が得られるようにするために、2 次キャッシュ内のこのオブジェクトのデータを手動でクリアする方法を使用できます
(この状況が発生する可能性は低くなります。

1.5 . 推奨事項
1. SQL を使用してデータ永続化オブジェクトのデータを直接更新しないことをお勧めしますが、一括削除は実行できます。 (システム内でバッチ更新が必要な場所も少なくなります)

2. SQL を使用してデータを更新する必要がある場合は、このオブジェクトのキャッシュされたデータをクリアする必要があります。
SessionFactory.evict(class)
SessionFactory.evict(class,id)
およびその他のメソッドを呼び出します。

3. バッチ削除データの量が大きくない場合は、Hibernate の SQL 実行によって生成されるキャッシュ データの一貫性の問題を回避する必要がないように、Hibernate のバッチ削除を直接使用できます。

4. 大量のレコード データを削除するために Hibernate のバッチ削除メソッドを使用することはお勧めできません。
その理由は、Hibernate の一括削除では 1 つのクエリ文と、条件を満たす n 個の削除文が実行されるためです。一度に 1 つの条件付き削除ステートメントを実行するのではなく。 !
削除するデータが大量にある場合、パフォーマンスに大きなボトルネックが発生します。 ! !一括して削除するデータの量が多い場合 (たとえば、50 件を超える場合)、JDBC を使用して直接削除できます。この利点は、SQL 削除ステートメントが 1 つだけ実行されるため、パフォーマンスが大幅に向上することです。同時に、キャッシュ データの同期の問題については、休止状態を使用して 2 次キャッシュ内の関連データをクリアできます。
SessionFactory.evict(class); およびその他のメソッドを呼び出します。

つまり、一般的なアプリケーション システム開発 (クラスター、分散データ同期の問題などを含まない) の場合、SQL 実行は中間関連付けテーブルの一括削除が実行されるときにのみ呼び出され、中間関連付けテーブルが一般的に実行条件となるためです。クエリは ID によってクエリを実行する可能性は低いです。したがって、この時点では、キャッシュクリアメソッドを呼び出すことなく、直接 SQL 削除を実行できます。そうすることで、今後 2 次キャッシュの構成によってデータの有効性の問題が発生することはなくなります。

一歩下がって、今後実際に中間テーブルオブジェクトをIDで問い合わせるメソッドが呼び出されたとしても、キャッシュをクリアするメソッドを呼び出すことで解決できます。

4. 具体的な設定方法
私の知る限り、多くの Hibernate ユーザーは、対応するメソッドを呼び出すときに「Hibernate がパフォーマンスの問題を自動的に処理してくれる」または「Hibernate が自動的にパフォーマンスの問題を処理してくれる」と迷信的に信じています。 「すべての操作はキャッシュを呼び出します」 実際の状況では、Hibernate は優れたキャッシュ メカニズムと拡張キャッシュ フレームワークのサポートを提供しますが、機能する前に正しく呼び出す必要があります。 !したがって、休止状態を使用する多くのシステムによって引き起こされるパフォーマンスの問題は、実際には休止状態が効果的でないか不良であることが原因ではなく、ユーザーが休止状態の使用方法を正しく理解していないことが原因です。それどころか、適切に設定されていれば、Hibernate のパフォーマンスには非常に「驚かされる」でしょう。以下に具体的な設定方法を説明します。

ibernate は 2 番目のキャッシュ インターフェイスを提供します:
net.sf.hibernate.cache.Provider、
net.sf.hibernate.cache.HashtableCacheProvider、
のデフォルト実装も提供します。 ehcache、jbosscache などの他の実装を構成することもできます。

具体的な設定場所は hibernate.cfg.xml ファイル内です
true
net .sf.hibernate.cache.HashtableCacheProvider

多くの Hibernate ユーザーは、このステップの設定が完了したと考えています
注: 実際、この設定では、Hibernate の 2 次キャッシュはまったく使用されません。同時に、休止状態を使用する場合、ほとんどの場合、セッションがすぐに閉じられるため、一次キャッシュは何の役割も果たしません。その結果、キャッシュは使用されず、すべての休止状態操作がデータベース上で直接実行されます。 !性能は期待通りです。

正しい方法は、上記の設定に加えて、各 vo オブジェクトの特定のキャッシュ戦略も設定し、マッピング ファイルで設定する必要があることです。例:



<キャッシュ使用法="read-write" / >

<プロパティ名="name" カラム="NAME" type="java.lang.String"/>
<プロパティ名="dbType" カラム="DBTYPE" type="java.lang.String"/ >


重要なのは、いくつかのオプション
read-only、read-write、クエリの実行時に注意してください。条件付きクエリ、またはすべての結果を返すクエリの場合、session.find() メソッドはキャッシュ内のデータを取得しません。キャッシュされたデータは、query.iterate() メソッドが呼び出されたときにのみ調整されます。

同時に、getメソッドとloadメソッドはキャッシュ内のデータをクエリします

キャッシュフレームワークごとに具体的な設定方法は異なりますが、一般的には上記の設定になります

(さらに、トランザクションをサポートするものについては)。

3. 要約

つまり、Hibernate は、さまざまなビジネス状況やプロジェクト状況に応じて効果的に構成され、正しく使用され、最大限の効果が得られます。その長所を見つけて短所を避けてください。あらゆる状況に対応できる万能の解決策はありません。


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート