SQLの論理的実行順序と物理的実行順序(オプティマイザ)の違い
はじめに
こんにちは。Sun* でバックエンドエンジニアをやっているうえひろです。
本記事では、SQLの「論理的な実行順序」と、実際の「物理的な実行順序」(SQLオプティマイザによる最適化)の違いについて考えてみたいと思います。
SQLの論理的な実行順序
SQLは、記述された順番そのままで処理されるわけではなく、データベースエンジンは次のような論理的な順序でクエリを実行します。
例えば、以下のSELECTクエリを考えてみましょう。
SELECT DISTINCT u.id, u.name, o.order_date
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.order_date > '2023-01-01'
GROUP BY u.id, u.name, o.order_date
HAVING COUNT(o.id) > 5
ORDER BY o.order_date DESC
LIMIT 10;
論理的実行順序
1. FROM(および JOIN/ON)
⇩
2. WHERE
⇩
3. GROUP BY
⇩
4. HAVING
⇩
5. SELECT(DISTINCT含む)
⇩
6. ORDER BY
⇩
7. LIMIT
このように、SQLは論理的には上記の手順に沿ってデータを処理します。
SQLオプティマイザによる物理的な実行順序
実際にSQLがデータベース上で実行される際は、SQLオプティマイザがクエリ全体を解析し、統計情報やインデックスの情報をもとに、最も効率的な実行計画を自動的に選択します。
そのため、論理的な実行順序とは異なる物理的な実行順序が採用される場合があります。
たとえば、以下のシンプルなクエリを見てみましょう。
SELECT * FROM users WHERE id = 1 LIMIT 1;
通常の論理的な順序は:
FROM
⇩
WHERE
⇩
SELECT
⇩
LIMIT
オプティマイザによる最適化の例
- idカラムにPRIMARY KEYインデックスが設定されていれば、データベースはフルテーブルスキャンせずにインデックスを使って該当する行をすぐに特定。
- LIMIT句があるため、最初の1行が見つかった時点で検索を終了する最適な手順(例えば 「WHERE → LIMIT → SELECT」)が採用される可能性がある。
つまり、実際にはオプティマイザが効率を重視して内部処理の順序を再構成しているのです。
EXPLAIN を使って実際の実行計画を確認する
SQLオプティマイザがどのような実行順序を選択したかを確認するには、EXPLAIN を使います。
EXPLAIN SELECT * FROM users WHERE id = 1 LIMIT 1;
出力例(MySQLの場合):
+----+-------------+-------+------------+------+---------------+---------+---------+-------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+-------------+
| 1 | SIMPLE | users | NULL | const| PRIMARY | PRIMARY | 4 | const | 1 |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+-------------+
- key=PRIMARY → id のプライマリキーインデックスを使用
- rows=1 → 1行のみ取得(テーブル全体のスキャンなし)
👉 この情報から、SQLオプティマイザが最適な実行順序を決定していることが分かる。
ただし、複雑なクエリの場合、EXPLAINが出力する情報はあくまで「概要」にとどまり、内部で行われる最適化処理のすべてが詳細に表示されるわけではありません。これもオプティマイザの内部動作がブラックボックス化されている一面です。
まとめ
✅ SQLの論理的な実行順序 は FROM(JOIN含む) → WHERE → GROUP BY → HAVING → SELECT(DISTINCT含む) → ORDER BY → LIMIT
の順で処理される。
✅ しかし、実際の処理順序(物理的な実行順序)はオプティマイザが最適化するため、変わることがある。
✅ EXPLAIN を使うと、オプティマイザが採用した実行計画(使用インデックス、アクセス方法、処理の概要など)を確認でき、クエリのパフォーマンス改善に役立つ。ただし、複雑なクエリでは内部の詳細な最適化処理すべてが表示されないこともある。
👉 補足: SQLの実行は、まず論理的な順序で処理されるという基本原則に基づいています。これを理解することで、なぜオプティマイザが実行順序を変更するのか、その背景がより明確になるでしょう。
Discussion