N+1クエリ問題とは、一覧データを1回のクエリで取得した後、各レコードの関連データを1件ずつ個別にクエリする結果、合計 N+1 回のデータベースアクセスが発生してしまうパフォーマンス上のアンチパターンである。
### N+1 の「N」と「1」 ORM(Object-Relational Mapping)やクエリビルダを使っていると、意識しないうちにこの問題を踏むことが多い。流れはこうだ。1. 親テーブルから一覧を取得する — これが「1」にあたるクエリ 2. 取得した N 件それぞれについて、子テーブルへ関連データを問い合わせる — これが「N」回のクエリ たとえば用語集の一覧ページを表示するケースを考える。
まず `glossaries` テーブルから 50 件を SELECT し、続いて各用語の翻訳データを `translations` テーブルから 1 件ずつ取得すると、合計 51 回のクエリが走る。件数が 500 になれば 501 回だ。### なぜ深刻なのか 1 回あたりのクエリが数ミリ秒で返るとしても、回数が線形に増えるため、データ量に比例してレスポンスタイムが悪化する。
ローカル開発では数十件しかないテーブルが本番では数千件に膨らみ、そこで初めて遅延が顕在化する——という事故は珍しくない。さらに、DB サーバーとアプリケーションサーバーがネットワーク越しに分離されている環境では、ラウンドトリップのオーバーヘッドが回数分だけ積み重なる。クエリ自体は軽くても、ネットワークレイテンシが支配的になるパターンだ。
### 解消のアプローチ 代表的な解決策は **eager loading**(事前読み込み)と **JOIN** の 2 つに大別できる。| 手法 | フレームワーク例 | 概要 | |------|----------------|------| | eager loading | Rails の `includes` / Django の `select_related` / Prisma の `include` | ORM が関連データをまとめて取得するクエリを自動生成する | | 明示的 JOIN | 生 SQL / Supabase の `.select("*, children(*)")` | 1 回のクエリで親子を結合して返す | | DataLoader パターン | GraphQL の DataLoader / Next.js の `cache()` | リクエスト内でキーを集約し、バッチクエリに変換する | Supabase を使う場合、PostgREST の埋め込みクエリ(`select("*, translations(*)")`)を活用すれば、アプリ側でループを書かずに 1 リクエストで関連データまで取得できる。### 検出と予防 開発段階で N+1 を見つけるには、クエリログの監視が有効だ。
PostgreSQL なら `log_min_duration_statement` を 0 に設定して全クエリをログに出し、同一パターンのクエリが連続していないか確認する。Rails には `bullet` gem、Django には `django-debug-toolbar` といった検出ツールもある。コードレビューの段階で「ループ内に await が入っていないか」を意識するだけでも、かなりの N+1 を未然に防げる。


A2A(Agent-to-Agent Protocol)とは、異なる AI エージェント同士が能力の発見・タスクの委譲・状態の同期を行うための通信プロトコルであり、Google が 2025 年 4 月に公開した。

Agent Skills とは、AI エージェントに特定のタスクや専門知識を実行させるために定義された再利用可能な命令セットであり、エージェントの能力を拡張するモジュール単位として機能する。

Agentic AI とは、人間の逐一の指示なしに目標を解釈し、計画の立案・実行・検証を自律的に繰り返す AI システムの総称である。


ATDD(Acceptance Test-Driven Development)とは、開発着手前に受け入れテストの基準をチーム全体で定義し、そのテストを自動化してから実装を進める開発手法である。