AIが返してきたSQLを前に、テストでは速いのに本番で重くなる予感を感じて一度手を止め、実行計画を確かめようとしている落ち着いた開発者

AIに書かせたSQLの確認ポイント|N+1・インデックス漏れ

「このデータの一覧、SQLで取りたいんだけど」とAIに頼むと、きれいなクエリがすぐ返ってきます。 コピーして実行。テスト環境ではパッと表示される。よし、次へ——。

その気持ち、よく分かります。SQLは書けなくはないけれど、毎回きっちり組むのは面倒だし、AIが出したものが動いているなら、それでいいじゃないか、と。でも、SQLは「動くかどうか」と「本番で速いかどうか」がまるで別の話なんですよね。テスト用の数十件では一瞬でも、本番の何万行・何十万行になった途端に、急に重くなる。しかもその原因は、画面を見ているだけでは気づけない所に潜んでいます。

この記事は、AIに書いてもらったSQL(と、それを呼ぶコード)を、本番に出す前に確かめる型の話です。全部を疑ってかかろう、という話ではありません。「動いた」の一歩先で、N+1・インデックス・取りすぎの3つだけ見る——それだけで、リリース後に「なんか遅い」と呼び出される事故がかなり減ります。責める話ではないので、気楽に読んでください。

結論:AIが書いたSQLは、3点だけ確認します。①N+1になっていないか(一覧を出すのに、1件ごとに追加のクエリを投げていないか。件数が増えるほど問い合わせ回数が跳ね上がる)、②絞り込みにインデックスが効くかWHEREJOINの条件列にインデックスがあるか。無いと全件走査になり、データが増えるほど遅くなる)、③取りすぎ・書き換えの危険はないかSELECT *で不要な列まで引いていないか、UPDATE/DELETEWHEREが付いているか)。確かめ方は、本番に近い件数を用意して、EXPLAINで実行計画を1回見るだけ。全件走査(Seq ScanやfullなどのScan)が出ていないか、想定どおりのインデックスが使われているかを見ます。迷ったらAIに「このクエリはN+1にならない?インデックスは何が要る?」と説明させてから判断する。SQLは、遅さが本番でしか出ないのがこわい所。出す前にひと目、実行計画を見るのが一番安い保険です。

一度に全部やろうとしなくて大丈夫です。 まずは「一覧を出すクエリだけ、本番くらいの件数で1回動かしてみる」。ここから始めましょう。

何が起きているのか——「動くSQL」と「速いSQL」は別物

AIが書いたSQLを本番に出す前に、N+1・インデックス・取りすぎの3つの門で順に確認してから採用する流れを示した図
本番に出す前に、N+1→インデックス→取りすぎの3つを順に見る。全部通ったものだけ採用

まず、なぜ確認が要るのかを共有させてください。AIのSQLが下手、という話ではありません。むしろ、文法として正しく、読みやすいクエリを返してくれることが多いです。問題は、AIが「あなたのデータが本番でどれくらいの量になるか」「どんなインデックスが張ってあるか」を知らないまま書いていることにあります。

AIは、渡された要件に対して「一般的に正しいSQL」を組みます。でも、速さはデータ量とインデックスと使われ方で決まる。ここはAIの手元に情報がありません。その結果、こんなことが起きます。

どれも共通するのは、テスト環境の少ないデータでは一見うまくいってしまうこと。だから「動いたからOK」で通ってしまい、遅さや事故は本番で初めて顔を出します。 ここで一拍おいて、回数・インデックス・取得量を見る。次から、その具体的な見方を順にいきます。

① N+1になっていないか——「一覧のたびに何回問い合わせている?」

いちばん多くて、いちばん効くのがN+1のチェックです。名前は難しそうですが、中身は単純で、「一覧を出すのに、1件ごとに追加の問い合わせを投げていないか」という話です。1回で済むはずが「1+N回」になるので、N+1と呼ばれます。

見つけ方は、SQL単体ではなくそれを呼ぶコードの側を見ます。

件数を増やして初めて見える:N+1は、テストの数件では体感できません。本番に近い件数を入れてから、表示にかかる時間と発行クエリ数を見るのが確実です。数件で「速いね」と判断しないのがコツです。

一覧・検索・詳細まとめ表示など、「複数件を扱う画面」ほどN+1が出やすいと覚えておくと、見る場所を絞れます。AIにコードを書かせる前提のそろえ方はAIにコードを書かせる前に渡す前提と制約、既存のコードに馴染ませる文脈の渡し方は既存コードベースにAIを馴染ませる文脈の渡し方も下敷きになります。

② インデックスが効くか——実行計画を1回だけ見る

N+1を潰しても、その1回のクエリ自体が遅ければ意味がありません。ここで見るのがインデックスです。インデックスは、本の索引のようなもの。無いと、データベースは目的の行を探すのにテーブルを丸ごと上から調べます(全件走査)。

確かめる決め手は、EXPLAINで実行計画を見ることです。クエリの前に EXPLAIN(データベースによっては EXPLAIN ANALYZE)を付けて実行すると、「このクエリを、データベースがどう処理するつもりか」が表示されます。難しく読み込まなくて大丈夫。最初は次の2点だけ見ます。

インデックスは万能ではありません。多すぎると書き込みが遅くなるし、あっても条件の書き方次第で効かないこともあります(列を関数で加工している、あいまい検索の先頭が%になっている、など)。ここは深追いせず、「よく絞り込む列に索引があるか」「実行計画で全件走査が出ていないか」の2点をまず押さえれば十分です。

AIに相談するなら、EXPLAINの結果を貼って「この実行計画、全件走査になってない?どの列にインデックスを張ると効く?」と聞くのが早いです。読み解きを手伝ってくれます。ただしAIの提案も鵜呑みにはせず、実際に張って計測して確かめる——この順番は崩さないでください。

③ 取りすぎ・危険な書き換えはないか——最後の安全確認

実在の速さの話が済んだら、最後に「取りすぎていないか」「危ない操作が混じっていないか」を確認します。ここは動かしても気づきにくく、あとから効いてくる所です。

判断に迷ったら、AI自身に説明させるのが手っ取り早いです。 「このクエリで取りすぎている列はない?WHEREの付け忘れや、入力をそのままつないでいる所はない?」と聞くと、危ない点が言葉になって出てきます。その説明を読んで納得できれば採用、あやしければ直す。受け取ったコード全体の見方はAI生成コードのレビュー・検証チェックリストに整理しています。

明日からやること(本番に出す前の3つ)

重い仕組みは要りません。まずこの3つだけ。

  1. 一覧・検索の画面で、発行クエリ数をログで1回見る:同じ形のクエリが何十回も並んでいたらN+1。まとめて取る形に直す。ここが一番効きます。
  2. 遅くなりそうなクエリにEXPLAINを1回かける:全件走査(Seq Scan / full / ALL)が出ていないか、狙った列にインデックスがあるかを見る。
  3. **SELECT *LIMITなし・WHEREなしの3つを目視で確認する**:取りすぎと危険な書き換えを、本番で流す前に1回だけチェックする。

この3つは、慣れれば合わせて数分です。本番で「なんか遅い」「データが消えた」と対応することを思えば、ずっと軽い。 全部を毎回きっちりやらなくても、「一覧はクエリ数を見る」から始めれば十分です。

AIに書かせたSQLの確認チェックリスト

本番に出す前に、さっと確認します。全部に○が要るわけではなく、そのクエリで気になる所だけで十分です。

① N+1(問い合わせ回数)

② インデックス(絞り込みの速さ)

③ 取りすぎ・安全

この記事のまとめ

AIが書くSQLは、たいてい文法として正しく、そのまま動きます。 それでも、本番に出す前のひと呼吸——N+1になっていないか、インデックスが効くか、取りすぎや危険な書き換えはないか——を挟むだけで、リリース後に効いてくる事故がずいぶん減ります。全部を疑う必要はありません。「一覧はクエリ数を見る」「怪しいクエリはEXPLAINを1回」。まずはこの一手からで十分です。

実行計画を確かめて安心し、落ち着いた表情で本番リリースへ進もうとしている開発者
一度確かめておけば、本番でも落ち着いていられる

SQLの速さは、本番でしか本当のことが分からない——だからこそ、出す前のひと目が効きます。 今日、「一覧のクエリ数を1回だけ見られた」なら、それはもう将来の自分を助ける一手です。受け取ったコード全体の見方はAI生成コードのレビュー・検証チェックリスト、そのまま使わないための動作確認は生成コードをそのまま使わない最低限の動作確認の型も、必要なときにのぞいてみてください。

よければ、こちらも

関連用語