Rails 7.2: counter_cacheをactiveオプションでオンオフ可能になった(翻訳)
カウンタキャッシュは、Railsアプリケーションのパフォーマンスを最適化するときの要となります。カウンタキャッシュは、モデルに関連付けられた多数のレコードを効果的にトラッキングし、データベースクエリを頻繁に発行する必要性を排除します。ただし既存のアプリケーション、特にテーブルが巨大なアプリケーションにカウンタキャッシュを追加するのは、多くの場合困難です。Rails 7.2では、まさにその問題に対処する素晴らしいアップデートが提供されています。
🔗 カウンタキャッシュを統合するときの課題
開発者が巨大なデータセットにカウンタキャッシュを導入しようとすると、主に以下の2つの課題に直面することになります。
- データのバックフィル(backfilling: 埋め戻し)をいかに効率よく行うか。
大量のデータを含んでいる既存のテーブルにカウンタキャッシュのカラムを追加すると、問題が発生することがあります。テーブルが長時間ロックされるとアプリケーションのパフォーマンスに重大な影響を及ぼす可能性が生じますが、これを防ぐには、カラムの追加とは別にカウンタキャッシュの値をバックフィルする必要もあります。バックフィル中は、ダウンタイムを最小限に抑えてユーザーエクスペリエンスが中断されないようにしつつ、データの整合性が損なわれない方法を慎重に検討しなければなりません。 -
データ整合性をいかに確保するか。
カウンタキャッシュをひとたび導入した後は、データ整合性をいかに損なわないようにするかが最も肝心です。カウンタキャッシュを内部で用いるsize
やany?
などのメソッドは、いかなる場合も正確な結果を返さなければなりません。しかしバックフィル処理中は、全レコードが正しく更新完了するまでの間、カウンタキャッシュから不正確なカウントが生成される可能性があります。
🔗 Rails 7.2でより安全なカウンタキャッシュが実装された
Rails 7.2の新しいアップデートによって、特に既存の巨大データセットが絡んでくるシナリオでのカウンタキャッシュをより効率的に管理できる機能が導入されました。カウンタキャッシュの設定にactive
オプションを導入することで、カウンタキャッシュをアクティブにするタイミングを開発者が制御できるようになります。
これによって、カウンタキャッシュの追加作業とは別にカウンタキャッシュのバックフィル作業を行えるようになり、テーブルのロックや潜在的なパフォーマンス問題の発生を最小化できます。バックフィル作業が完了したら、このオプションでカウンタキャッシュを有効にすることで、アプリケーションのパフォーマンスを犠牲にせずに関連付けの正確なカウントを得られるようになります。
Railsにおけるこのアップデートの実装を説明するために、記事(articles)とコメント(comments)を扱うシンプルなブログアプリケーションを例にすることにします。
このブログアプリケーションでは、1件の記事に複数のコメントを付けられます。ここで、個別の記事に何件のコメントが関連付けられているかをトラッキングするために、カウンタキャッシュを追加したいとします。
ただし、データベースには既に大量のデータがあるため、従来の方法でカウンタキャッシュを実装するのは困難だとします。
🔗 実装の手順
- 1. 関連付けを定義します。
最初にArticle
モデルとComment
モデルの間に関連付けを定義し、counter_cache
にactive: false
オプションを指定して、初期セットアップ中はカウンタキャッシュを無効にしておきます。
class Comment < ApplicationRecord
belongs_to :article, counter_cache: { active: false }
end
- 2. カウンタキャッシュをバックフィルします。
関連付けの設定が完了したら、articles
テーブルのカウンタキャッシュ用カラムのバックフィルに取りかかります。この作業中はカウンタキャッシュが無効になっており、size
やany?
などのメソッドは(カウンタキャッシュを使わずに)データベースから直接結果を取得します。これによって、バックフィル作業中に誤った値が表示されることを防ぎます。 -
3. カウンタキャッシュを有効にします。
バックフィル作業が完了したら、counter_cache
定義からactive: false
オプションを削除することで、カウンタキャッシュを有効にします。
class Comment < ApplicationRecord
belongs_to :article, counter_cache: true
end
有効になったカウンタキャッシュは関連付けに統合されるようになり、1記事ごとに関連付けられているコメントの件数が効果的にトラッキングされるようになります。
active
オプションは#51453で導入されました。この機能に関するすべての議論は以下のdiscussをご覧ください。
概要
元サイトの許諾を得て翻訳・公開いたします。
日本語タイトルは内容に即したものにしました。
参考: 週刊Railsウォッチ20240416: カウンタキャッシュからの読み出しを
counter_cache: { active: false }
で制御できるようになった参考: Add the ability to ignore counter cache columns while they are backfilling by fatkodima · Pull Request #51453 · rails/rails