performance-optimization について
Rails 8 開発者向けのパフォーマンス最適化ガイドです。データベースクエリ、メモリ管理、応答時間の分析を扱い、検出・分析・修正・検証の手順で最適化パターンを示します。
主な機能
- 01N+1 クエリの検出と防止
- 02クエリとデータベースインデックスの最適化
- 03クエリプランと低速クエリの分析
- 04メモリ使用量と性能のプロファイリング
- 05大規模データセットのバッチ処理
活用シーン
- 01ページリクエストの N+1 クエリ調査
- 02大規模データセット処理の最適化
- 03低速クエリとインデックス要件の分析
- 04アプリケーションのメモリ問題の特定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ thibautbaissac/ rails_ai_agents --skill performance-optimizationインストール後、Claude Code で/performance-optimizationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/memory-and-profiling.mdn-plus-one.mdquery-optimization.md詳細
Rails 8 のパフォーマンス最適化
概要
パフォーマンス最適化では、次の点に重点を置きます。
- N+1 クエリの検出と防止
- クエリの最適化
- メモリ管理
- レスポンスタイムの改善
- データベースのインデックス作成
クイックスタート
# Gemfile
group :development, :test do
gem 'bullet' # N+1 detection
gem 'rack-mini-profiler' # Request profiling
gem 'memory_profiler' # Memory analysis
end
N+1 クエリの検出と防止
N+1 クエリは、コードがコレクションを読み込んだ後、関連する各レコードに対して個別にクエリを実行すると発生します。Bullet gem はこれらを自動的に検出します。includes、preload、または eager_load を使った先読みで修正します。
先読みの選択表
| メソッド | 使用する場面 |
|---|---|
includes | ほとんどの場合(Rails が最適な方法を選択します) |
preload | 個別のクエリを強制する場合、大規模なデータセット |
eager_load | 関連付けで絞り込む場合、単一のクエリが必要な場合 |
joins | 絞り込みのみが必要で、関連データが不要な場合 |
主なパターン:Bullet の設定、先読みメソッド、スコープ付きの先読み、カウンターキャッシュ、クエリ数のアサーションを使った N+1 のテスト。
すべてのコード例とパターンについては、references/n-plus-one.md を参照してください。
クエリの最適化
必要なカラムだけを選択し、大規模なデータセットにはバッチ処理を使い、効率的な存在確認方法を選ぶことで、クエリを最適化します。
主なパターン
| パターン | 悪い例 | 良い例 |
|---|---|---|
| カラムの選択 | User.all.map(&:name) | User.pluck(:name) |
| 大量の反復処理 | Event.all.each { ... } | Event.find_each { ... } |
| 存在確認 | .any? / .present? | .exists? |
| コレクションのサイズ | .length(すべて読み込む) | .size(効率的) |
データベースのインデックス作成
外部キー、WHERE/ORDER BY/JOIN 句で使われるカラム、一意制約にインデックスを追加します。複数カラムを使うクエリには複合インデックスを使います。絞り込んだサブセットには部分インデックスを使います。
クエリの分析
Event.where(...).explain(:analyze) を使ってクエリプランを調べます。ActiveSupport::Notifications を使って低速クエリのログを設定し、しきい値を超えるクエリを検出します。
すべてのコード例とパターンについては、references/query-optimization.md を参照してください。
メモリ管理とプロファイリング
memory_profiler を使ってメモリの問題を検出します。AR オブジェクト全体の読み込みより pluck を優先し、ストリーミングには find_each を使い、一括操作には update_all/in_batches を使います。
Rack Mini Profiler
開発環境でリクエストごとのプロファイリングを行います。クエリ数、実行時間、フレームグラフ(stackprof gem を使用)を表示します。プロファイラーバッジ、または ?pp=flamegraph からアクセスできます。
すべてのコード例とパターンについては、references/memory-and-profiling.md を参照してください。
クイック修正リファレンス
| 問題 | 解決策 |
|---|---|
| belongs_to での N+1 | includes(:association) |
| has_many での N+1 | includes(:association) |
| COUNT が遅い | counter_cache を追加する |
| すべてのカラムを読み込む | select または pluck を使う |
| 大規模なデータセットの反復処理 | find_each を使う |
| 外部キーのインデックスがない | *_id カラムにインデックスを追加する |
| WHERE 句が遅い | 絞り込みに使うカラムにインデックスを追加する |
| 未使用の関連付けを読み込む | includes から削除する |
パフォーマンスチェックリスト
- 開発環境/テスト環境で Bullet が有効になっている
- 重要な処理経路で N+1 クエリが発生しない
- 外部キーにインデックスがある
- 頻繁な件数取得にカウンターキャッシュを使っている
- コントローラーで先読みを行っている
- 大規模なデータセットにバッチ処理を使っている
- 低速なエンドポイントのクエリを分析している
ワークフロー
- 検出 -- Bullet を有効にし、テストを実行して、Rack Mini Profiler を確認します
- 分析 --
explain(:analyze)を使い、低速クエリのログを確認して、メモリをプロファイリングします - 修正 -- リファレンスファイルから適切なパターンを適用します
- 検証 -- テストを再実行し、クエリ数を確認して、プロファイラーを確認します
参考ファイル
- references/n-plus-one.md -- N+1 検出、先行読み込みの方法、Bullet の設定、カウンターキャッシュ、テストパターン
- references/query-optimization.md -- カラムの選択、バッチ処理、インデックス戦略、EXPLAIN による分析、スロークエリのログ記録
- references/memory-and-profiling.md -- メモリプロファイラーの使用方法、メモリ効率の高いパターン、Rack Mini Profiler のセットアップ、デプロイのチェックリスト