9

を使用してモデルの1つで行を合計しており、Model.countパフォーマンスについて少し心配しています。最終的に、このモデルは非常に大きくなり、したがってSELECT COUNT (*)非常に遅くなります。

関係counter_cacheなく使用する方法はありますか?:belongs_toまたは、行をカウントする別のパフォーマンスに適した方法ですか?別のモデルを作成することを考えました。このような計算を保存するモデルだけですが、それが最善の方法かどうかはわかりません。

4

4 に答える 4

13

Cacheモデルを作成するよりも簡単なのは、 を使用することRails.cacheです。

Rails.cache.read("elephant_count") #=> nil
Rails.cache.write("elephant_count", 1) #=> true
Rails.cache.read("elephant_count") #=> 1

Rails はデフォルトでファイル ストア (tmp/cache) を使用します。

次に、Rails.cache.write のインクリメントとデクリメントをモデルafter_createafter_destroyフックにModel.size配置し、Rails.cache.read の呼び出しでオーバーライドします。

initialize_cache.rbconfig/initializers に次のような名前のファイルを配置することで、Rails が最初に初期化するたびにキャッシュを初期化できます。

Rails.cache.write('elephant_count', 0) if Rails.cache.read('elephant_count').nil?
于 2011-05-12T02:17:40.183 に答える
11

カウンターを維持したい場合は、それを使用するcounter_cacheか手動で行うかに関係なく、Rails はコールバックを使用してカウンターを維持します。これにより、新しい子孫が作成/破棄されたときにカウンターが増加/減少します。

親だけが子の数を保存できるためcounter_cache、リレーションシップを使用せずに a を保存する方法を知りません。belongs_to

計量性能

テーブルが「大きく」なる場合は、テスト データベースに多数の行を入力してから、SQL クエリの実行を開始してEXPLAIN、データベース クエリのパフォーマンスを取得します。でレコードの作成/破棄を行う際のパフォーマンス ヒットがcounter_cache、最初にこれらのカウンターにアクセスする必要がある頻度によって相殺されるかどうかを確認します。

カウンターが常に 100% 正確である必要がない場合は、代わりに、cronジョブまたはバックグラウンド ワーカーを使用してキャッシュを定期的に更新できます。

要約すれば:

  1. レコードの作成/破棄にかかるわずかに長い時間を相殺するのに十分なカウンターが必要な場合にのみ、 counter_cache を使用する必要があります。
  2. counter_cache私の知る限り、コールバックを使用する手動の代替手段を使用すると、パフォーマンスが大幅に低下する可能性はほとんどありません。
  3. キャッシュが正確である必要がない場合は、それを利用して計算の実行頻度を減らします。
于 2011-05-12T01:46:22.383 に答える
6

http://guides.rubyonrails.org/caching_with_rails.htmlをご覧ください 。具体的には、キャッシュ ストアに関するセクションをご覧ください。キャッシュ ストアを使用すると、任意のものの値をキャッシュに格納できます。

たとえば、get_count と呼ばれるモデルで呼び出されるメソッドを持つことができます。これは、最初は count で満たされますが、after_create コールバックで 1 ずつインクリメントされます。最新の状態に保つ必要がない場合は、x 分ごとにこれを更新して、ほぼ正確にすることができます。

私は個人的に、このようなもののストアとして memcache を使用しています。必要に応じて、キャッシュを最新の状態に保つようにしてください。

于 2011-05-12T01:43:08.150 に答える