3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

非効率なSQLをAIで劇的に改善!実行時間10倍高速化への道

Last updated at Posted at 2025-12-20

💡 はじめに

データベースのパフォーマンスは、アプリケーションのユーザー体験に直結します。特に大規模なデータセットを扱う場合、冗長で非効率なSQLクエリは、システムのボトルネックとなり、開発者の時間を奪います。

本記事では、意図せず「実行時間の遅いクエリ」を書いてしまった場合を想定し、近年進化が著しいAI(特に大規模言語モデル, LLM)を活用して、クエリを 「スマートで高速なクエリ」 へと劇的に改善する具体的な手法を、サンプルコード付きで解説します。

😱 改善前の「遅いクエリ」とその問題点

今回は、商品の注文履歴から、過去90日間に注文が全くない顧客(アクティブではない顧客)のリストを取得するケースを考えます。

非効率な書き方として、サブクエリ内で大量のデータを繰り返しスキャンしてしまうようなクエリを見てみましょう。

📄 サンプルクエリ(遅い例)

SQL
-- 顧客テーブル
CREATE TABLE customers (
    customer_id INT PRIMARY KEY,
    name VARCHAR(100),
    created_at DATETIME
);

-- 注文テーブル
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    order_date DATETIME,
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);

-- 90日間注文がない顧客リストを取得するクエリ
SELECT 
    c.customer_id, 
    c.name
FROM 
    customers c
WHERE 
    c.customer_id NOT IN (
        SELECT 
            o.customer_id
        FROM 
            orders o
        WHERE 
            o.order_date >= DATEADD(day, -90, GETDATE()) -- SQL Serverの日付関数
    );

💣 このクエリのパフォーマンス上の問題点

  1. NOT IN の使用:
    • NOT IN は、内側のサブクエリが返す全データに対して外部クエリのレコードを一つずつ比較するため、処理が非常に重くなります。特に、SQL Serverでは、サブクエリがNULLを含む場合、期待しない結果(全てのレコードが除外される)を引き起こす可能性があり、非常に危険です。
  2. インデックスの非活用:
    • この形式のサブクエリでは、オプティマイザが効率的な実行計画を立てにくく、orders テーブルの order_datecustomer_id にインデックスがあっても、その恩恵を最大限に受けられないことがあります。
  3. データ量の増加に弱い:
    • customers テーブルと orders テーブルのデータ量が増えるにつれて、実行時間が二次関数的に増加する傾向があります。

🤖 AIによる改善提案と高速化

この遅いクエリを、開発者向けのAIツールに 「このSQL Serverのクエリの実行速度を改善したい。より効率的な書き方を提案してください。」 と入力してみましょう。

AIは、上記のパフォーマンス上の問題点を認識し、一般的にSQL Serverで推奨される高速化手法を用いたクエリを提案してくれます。

📄 AIが提案する改善クエリ(速い例)

AIは、NOT IN の代わりに LEFT JOINWHERE IS NULL の組み合わせ、または NOT EXISTS の利用を提案する可能性が高いです。これらはSQL Serverにおいても最も推奨されるパフォーマンス改善手法です。

1. LEFT JOIN + WHERE IS NULL による改善

SQL
-- LEFT JOINとWHERE IS NULLを使用して、注文がない顧客を見つける
SELECT
    c.customer_id,
    c.name
FROM
    customers c
LEFT JOIN
    orders o ON c.customer_id = o.customer_id
    AND o.order_date >= DATEADD(day, -90, GETDATE()) -- JOIN条件でフィルタリング
WHERE
    o.order_id IS NULL; -- 注文レコードが見つからなかった(=注文がない)顧客のみを選択

2. NOT EXISTSによる改善

SQL
-- NOT EXISTSを使用して、関連する注文が存在しない顧客を見つける
SELECT 
    c.customer_id, 
    c.name
FROM 
    customers c
WHERE 
    NOT EXISTS (
        SELECT 
            1 -- 存在チェックなので列は何でも良い
        FROM 
            orders o
        WHERE 
            o.customer_id = c.customer_id -- 外部クエリのcustomer_idに紐づく
            AND o.order_date >= DATEADD(day, -90, GETDATE())
    );

✨ 改善クエリの優位性

改善手法 優位性(なぜ速いか)
LEFT JOIN + WHERE IS NULL 結合処理はオプティマイザが最適化しやすく、インデックスも活用しやすい。データスキャンが一度で済むため、非常に高速。
NOT EXISTS 内部クエリは一致するレコードが見つかった時点でスキャンを停止する(ショートサーキット評価)。NOT INのように全件スキャンやNULL値の評価で苦しむことがない。

実際にSQL Server環境で、これらの改善クエリは元の NOT IN クエリと比較して 数倍から数十倍の速度向上 が見込めます。特に大規模なテーブルでは、実行計画 の違いが明確に現れます。

🛠️ AIをパフォーマンス改善に活用するステップ

AIを単なるコードジェネレータとしてではなく、優秀なデータベースエンジニアとして活用するためのステップです。

  1. 遅いクエリを特定する:
    • まず、SQL Server Management Studio (SSMS) で実行計画拡張イベントを確認し、実行時間がかかっているクエリを特定します。
  2. AIに相談する:
    • 特定したクエリと、対象テーブルのスキーマ情報(CREATE TABLE 文など)をAIに渡し、「SQL Server環境で、このクエリを高速化する、より効率的な書き方を提案してください」と依頼します。
  3. 提案されたクエリを検証する:
    • AIの提案をそのまま本番環境に適用せず、必ずテスト環境で実行し、期待通りの結果を返すか、そして本当に速くなっているかを実際の実行計画Actual Execution Plan)で確認します。
  4. インデックスの提案も求める:
    • AIはクエリの書き方だけでなく、「このクエリが遅い原因は、orders テーブルの (customer_id, order_date) に対する非クラスター化インデックスがないことかもしれません」といった、インデックス戦略の提案も行ってくれます。

🎯 まとめ

AIは、私たちが気づかないSQLのアンチパターンや、特定のDBMS(SQL Serverなど)で最適な書き方といった知識を一瞬で提供してくれます。

  • SQL Serverにおいて NOT IN非効率であり、特にNULL値のリスクを伴います。

  • AIは、これらを LEFT JOIN + IS NULLNOT EXISTS といった高速かつ安全な手法に変換するのに役立ちます。

  • 最も重要なのは、AIの提案を鵜呑みにせず、 SSMSで実行計画を確認し、論理的に最も速いクエリを選択する というエンジニアの姿勢です。

AIを良き相棒として、日々のクエリ改善に取り組み、快適なアプリケーション開発を目指しましょう!

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?