N+1問題シミュレーター
データ件数が増えると処理が遅くなる N+1問題 を視覚的に体験
例えば、管理画面に「顧客一覧」を表示するとします。顧客ごとに会社情報などの関連データも表示する場合、コードの書き方しだいでデータベースへの問い合わせ回数が何倍にも変わります。下の設定を動かして、その差を体験してみてください。
1. 設定を変更する
※増えるほどN+1問題発生時のクエリ回数が急増します
2. なぜ差が出る? 実行コードの比較
このシミュレーターは、次のようなJavaScriptコード(データベース部分は簡略化した擬似メソッド)を実行した場合の違いを再現しています。設定を変えるとコードも変わります。
3. SQL風 データベース実行ログ
データベースに対して発行されるクエリコマンドのログです。設定を変えると連動してクエリが変わります。
4. ユーザーに表示される顧客一覧画面のイメージ
最終的にユーザーの画面に表示される顧客一覧です。見た目は同じでも裏側のクエリ回数が違います。赤いセルの1つ1つが、改善前の書き方で「クエリ1回」が発生している箇所です。
| 顧客名 | 会社情報 | 住所 | 連絡先 | 購入履歴 | 会員ランク |
|---|
シミュレータに基づく状況解説
使い方ガイド & N+1問題とは?
シミュレーターの使い方
- ステップ 1: 「顧客件数」スライダーを左右に動かすか、プリセットボタンを押して一覧に表示する顧客数を変更します。
- ステップ 2: 「関連データ」のチェックボックスをON/OFFして、1人の顧客に紐付ける情報の数を変えてみてください。
- ステップ 3: 「実行コードの比較」や「SQL風ログ」で、「N+1問題あり(改善前)」と「まとめて取得(改善後)」のクエリ回数・想定処理時間の違いを観察します。
N+1問題とは何か?
一覧画面(顧客一覧や商品一覧など)を表示する際、主データ(顧客など)を1回取得したあと、関連するデータ(会社情報など)を顧客の数(N回)だけ個別にデータベースに問い合わせてしまう現象です。
この結果、1回(主データの取得) + N回(関連データの取得) = 合計 N+1 回のクエリが発行されてしまい、データ件数が増えるにつれて急激に処理が重くなります。
どうやって解決する?
ORMの「Eager Loading(Laravelの `with` や Railsの `includes`)」を使用するか、SQLで「JOIN(左外部結合)」や「IN句による一括取得」を行うことで、関連データをあらかじめまとめて取得するようにコードを書き換えます。これにより、データ件数に関わらずクエリ回数を最小限に抑えることができます。
※ 本ツールはN+1問題の仕組みを直感的に理解するための簡易シミュレーターです。実際のデータベース環境、インデックス設定、クエリキャッシュ、ネットワーク遅延等によって処理時間は変化します。ここではわかりやすさを優先し、1つのクエリの実行コストを20msとして算出しています。
