Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 7.2: counter_cacheをactiveオプションでオンオフ可能になった(翻訳)

Rails 7.2: counter_cacheをactiveオプションでオンオフ可能になった(翻訳)

カウンタキャッシュは、Railsアプリケーションのパフォーマンスを最適化するときの要となります。カウンタキャッシュは、モデルに関連付けられた多数のレコードを効果的にトラッキングし、データベースクエリを頻繁に発行する必要性を排除します。ただし既存のアプリケーション、特にテーブルが巨大なアプリケーションにカウンタキャッシュを追加するのは、多くの場合困難です。Rails 7.2では、まさにその問題に対処する素晴らしいアップデートが提供されています。

🔗 カウンタキャッシュを統合するときの課題

開発者が巨大なデータセットにカウンタキャッシュを導入しようとすると、主に以下の2つの課題に直面することになります。

  • データのバックフィル(backfilling: 埋め戻し)をいかに効率よく行うか。
    大量のデータを含んでいる既存のテーブルにカウンタキャッシュのカラムを追加すると、問題が発生することがあります。テーブルが長時間ロックされるとアプリケーションのパフォーマンスに重大な影響を及ぼす可能性が生じますが、これを防ぐには、カラムの追加とは別にカウンタキャッシュの値をバックフィルする必要もあります。バックフィル中は、ダウンタイムを最小限に抑えてユーザーエクスペリエンスが中断されないようにしつつ、データの整合性が損なわれない方法を慎重に検討しなければなりません。

  • データ整合性をいかに確保するか。
    カウンタキャッシュをひとたび導入した後は、データ整合性をいかに損なわないようにするかが最も肝心です。カウンタキャッシュを内部で用いるsizeany?などのメソッドは、いかなる場合も正確な結果を返さなければなりません。しかしバックフィル処理中は、全レコードが正しく更新完了するまでの間、カウンタキャッシュから不正確なカウントが生成される可能性があります。

🔗 Rails 7.2でより安全なカウンタキャッシュが実装された

Rails 7.2の新しいアップデートによって、特に既存の巨大データセットが絡んでくるシナリオでのカウンタキャッシュをより効率的に管理できる機能が導入されました。カウンタキャッシュの設定にactiveオプションを導入することで、カウンタキャッシュをアクティブにするタイミングを開発者が制御できるようになります。

これによって、カウンタキャッシュの追加作業とは別にカウンタキャッシュのバックフィル作業を行えるようになり、テーブルのロックや潜在的なパフォーマンス問題の発生を最小化できます。バックフィル作業が完了したら、このオプションでカウンタキャッシュを有効にすることで、アプリケーションのパフォーマンスを犠牲にせずに関連付けの正確なカウントを得られるようになります。

Railsにおけるこのアップデートの実装を説明するために、記事(articles)とコメント(comments)を扱うシンプルなブログアプリケーションを例にすることにします。
このブログアプリケーションでは、1件の記事に複数のコメントを付けられます。ここで、個別の記事に何件のコメントが関連付けられているかをトラッキングするために、カウンタキャッシュを追加したいとします。
ただし、データベースには既に大量のデータがあるため、従来の方法でカウンタキャッシュを実装するのは困難だとします。

🔗 実装の手順

  • 1. 関連付けを定義します。
    最初にArticleモデルとCommentモデルの間に関連付けを定義し、counter_cacheactive: falseオプションを指定して、初期セットアップ中はカウンタキャッシュを無効にしておきます。
class Comment < ApplicationRecord
  belongs_to :article, counter_cache: { active: false }
end
  • 2. カウンタキャッシュをバックフィルします。
    関連付けの設定が完了したら、articlesテーブルのカウンタキャッシュ用カラムのバックフィルに取りかかります。この作業中はカウンタキャッシュが無効になっており、sizeany?などのメソッドは(カウンタキャッシュを使わずに)データベースから直接結果を取得します。これによって、バックフィル作業中に誤った値が表示されることを防ぎます。

  • 3. カウンタキャッシュを有効にします。
    バックフィル作業が完了したら、counter_cache定義からactive: falseオプションを削除することで、カウンタキャッシュを有効にします。

class Comment < ApplicationRecord
  belongs_to :article, counter_cache: true
end

有効になったカウンタキャッシュは関連付けに統合されるようになり、1記事ごとに関連付けられているコメントの件数が効果的にトラッキングされるようになります。

activeオプションは#51453で導入されました。この機能に関するすべての議論は以下のdiscussをご覧ください。

参考: New feature to make introducing counter caches safer and easier - rubyonrails-talk - Ruby on Rails Discussions

関連記事

Rails: Active Recordコールバックを使わずにカウンタキャッシュを更新する(翻訳)

Rails向け高機能カウンタキャッシュ gem「counter_culture」README(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。