Hibernateで常に第2レベルのキャッシュを使用しますか、それとも最初にそれを使用せずに試し、パフォーマンスが低下した場合にのみ使用しますか?
7 に答える
最初に機能させてから、高速化します。キャッシュが必要ない場合は、実装しないでください。
私が行ったアプリケーションでは、データベースは複数のアプリケーション間で共有されており、そのうちのいくつかはまったく Java ではありません。したがって、他のアプリがいつデータベースを更新できるかわからないため、このような状況では二次キャッシュは選択肢になりません。
私の Hibernate の使用は、常に別のフレームワーク (Spring など) のコンテキストで行われており、キャッシュを有効にすることはほとんど簡単なことではありません。これらのプロジェクトの多くは、いくつかの重要なドメイン クラスに対してehcacheによるキャッシュを利用しています。
そうは言っても、これはリソース間のトレードオフを行わなければならないもう 1 つの領域です。つまり、取得パフォーマンスとメモリ使用量のバランスを取ります。測定を伴わない最適化は、不適切な方法であることが何度も示されてきました。
アプリケーションのパフォーマンスに関する指標を収集します。次に、スロー スポットに対処する方法を決定します。キャッシングはあなたの心配の中で最も少ないかもしれません.
最初は使用せずに試して、パフォーマンスが低下した場合にのみ使用します。
正しいことを行えば (select N+1 などに注意してください)、ほとんどの場合、2 番目のレベルのキャッシュがなくてもパフォーマンスは許容できるはずです。
現在、これに関連する休止状態固有の問題があります。そして、悪名高い LazyInitializationException. 基本的に、エンティティが永続コンテキストにアタッチされている間、すべての遅延関連付けを初期化する必要があります。これを行うには、次の 2 つの方法があります。
- リレーションシップに手動でアクセスして強制的にロードします。
- 結合フェッチを指定するクエリを使用します。
これら 2 つのアプローチでは、まったく異なるコード部分が生成されるため、一方を他方に移行するのはかなりの作業になる可能性があります。問題は、アプローチ 1. では、第 2 レベルのキャッシュを使用しない場合に多数のクエリが発生することです。そのため、人々はアプローチ 2 を使用することを決定でき、その結果、フィーバー クエリが発生します。ただし、後で第 2 レベルのキャッシュをオンにすると、アプローチ 2 のクエリはキャッシュからデータをロードせず、結果のエンティティをキャッシュに格納するため、キャッシュがない場合よりもクエリの実行が遅くなります。これにより、クエリ キャッシュを使用する必要があるなどの複雑な問題が発生します。
そのため、(この特定のケースでは) 最初にすべてのエンティティに対してキャッシュを有効にする方が良いと思われますが、これは通常は些細なことですが、開発が進むにつれて必要のないエンティティに対しては無効にします。
有名な Donald Knuth の言葉を引用すると、「プログラマーは、プログラムの重要でない部分の速度について考えたり、心配したりするために膨大な時間を浪費します。これらの効率化の試みは、実際には、デバッグやメンテナンスを検討する際に大きなマイナスの影響を及ぼします。 97% の確率で、小さな効率性を忘れてしまいます。時期尚早の最適化はすべての悪の根源です。しかし、その重要な 3% の機会を逃してはなりません。」
パフォーマンスの問題が発生した場合にのみ、最適化を開始できます。また、最大のボトルネックのみを最適化し、必要に応じてそれを下げる必要があります。
ただし、NHibernate でこの最適化を実装しても、ほとんどの状況でデバッグとメンテナンスに与える影響はごくわずかであり、コードへの最小限の追加で実装できることがよくあります。
遅延読み込みに大きく依存し、読み取り専用のテーブルがあり、NHibernate を使用しないアプリケーションとの同時実行性について心配する必要がなく、パフォーマンスが問題であり、第 2 レベルのキャッシュを使用して最適化する方法に精通している場合 (つまり、既に答えを知っていることを意味します)この質問に)、2 番目のレベルのキャッシュを使用する必要があります。