404 Not Found

404 Not Found


nginx

MySQL クエリと EXPLAIN 実行計画の概要

インデックスの高度な機能を理解してこそ、真に高性能なクエリを作成することができます。

このレッスンでは、インデックスの種類とEXPLAIN解析について詳しく解説します。

1. 学習内容


2. クラスタ化インデックスと非クラスタ化インデックス

ディメンション クラスタ化インデックス 非クラスタ化インデックス
保存方法 データとインデックスは一緒に保存される インデックスはデータのアドレスを指し示す
数量 1つまで 複数可
主キー InnoDB は自動的に主キーを使用します セカンダリインデックス
クエリ データを直接取得 テーブルの参照が必要

(1) テーブルでの検索

100%
graph LR
    A[Secondary Index<br/>idx_email] -->|Primary Key Value| B[Clustered Index<br/>PRIMARY]
    B -->|Complete Data| C[Data Row]
SQL
-- The process of table lookup
SELECT * FROM users WHERE email = 'alice@email.com';
-- 1. Find id=1 in idx_email
-- 2. Find complete data for id=1 in PRIMARY

3. カバレッジ・インデックス

クエリに含まれるすべてのフィールドがインデックスに含まれているため、テーブルを参照する必要はありません。

▶ 例:オーバーレイインデックス

SQL
-- Create a composite index
CREATE INDEX idx_name_email ON users(username, email);

-- Covering Index(No need to return to the table)
SELECT username, email FROM users WHERE username = 'alice';

-- Non-covering index(Need to return to the table)
SELECT * FROM users WHERE username = 'alice';
▶ 試してみよう
タイプ テーブルに戻る パフォーマンス
索引 番号 高速
非カバレッジインデックス はい 遅い

4. 複合インデックスと最左プレフィックス

(1) 最左前置詞の原則

複合インデックス (a, b, c) は、以下のクエリで使用できます:

SQL
WHERE a = 1                    -- ✅ Using index
WHERE a = 1 AND b = 2         -- ✅ Using index
WHERE a = 1 AND b = 2 AND c = 3  -- ✅ Using index
WHERE b = 2                    -- ❌ Index not used
WHERE b = 2 AND c = 3         -- ❌ Index not used

▶ 例:インデックスの使用状況の確認

SQL
CREATE INDEX idx_abc ON orders(customer_id, status, order_date);

-- ✅ Using index
EXPLAIN SELECT * FROM orders WHERE customer_id = 1;
EXPLAIN SELECT * FROM orders WHERE customer_id = 1 AND status = 'paid';
EXPLAIN SELECT * FROM orders WHERE customer_id = 1 AND status = 'paid' AND order_date > '2026-01-01';

-- ❌ Index not used (Violates the Leftmost Prefix Rule)
EXPLAIN SELECT * FROM orders WHERE status = 'paid';
▶ 試してみよう

5. インデックスが効果を発揮しなくなるケース

シナリオ 理由
関数の演算 WHERE YEAR(date) = 2026 関数で囲まれたインデックス
暗黙の型変換 WHERE phone = 13800001111 数値を用いた文字列配列の検索
LIKE Left Fuzzy WHERE name LIKE '%john' 接頭辞不明
OR 条件 WHERE a = 1 OR b = 2 一部のフィールドにインデックスが設定されていない
NOT IN/NOT EXISTS WHERE id NOT IN (1,2) オプティマイザがフルテーブルスキャンを選択
IS NULL/IS NOT NULL WHERE col IS NULL NULLの割合による

▶ 例:インデックスの障害と復旧

SQL
-- ❌ Index Invalidation
SELECT * FROM users WHERE YEAR(created_at) = 2026;

-- ✅ Fix: Change to a range query
SELECT * FROM users WHERE created_at >= '2026-01-01' AND created_at < '2027-01-01';

-- ❌ Index Invalidation
SELECT * FROM users WHERE phone = 13800001111;

-- ✅ Fix: Use quotes
SELECT * FROM users WHERE phone = '13800001111';
▶ 試してみよう

6. 実行計画のEXPLAIN

▶ 例:EXPLAIN の使用

SQL
EXPLAIN SELECT * FROM users WHERE email = 'alice@email.com';
▶ 試してみよう

出力:

TEXT
+----+-------+------+---------+------+----------+-------+
| id | type  | key  | key_len | ref  | rows     | Extra |
+----+-------+------+---------+------+----------+-------+
|  1 | const | idx_email | 402 | const | 1 |       |
+----+-------+------+---------+------+----------+-------+

(1) 主要フィールドの説明

フィールド 説明 有効な値
アクセス種別 const > eq_ref > ref > range > index > ALL
キー 使用されるインデックス NULL不可
行数 スキャン対象となる行数の推定値 数値が低いほど良い
補足 追加情報 インデックスの使用(カバリング・インデックス)

(2) アクセス型

種類 説明 メリット・デメリット
const 主キー/一意インデックスによる等値クエリ ⭐⭐⭐
eq_ref 結合には主キーまたは一意インデックスを使用する ⭐⭐⭐
ref 一意でないインデックスに対する等値クエリ ⭐⭐
範囲 インデックス範囲クエリ ⭐⭐
インデックス インデックスの完全スキャン
すべて テーブル全体のスキャン

❓ よくある質問

Q 複合インデックスのフィールド順序はどのように決めるべきですか?
A 選択性の高いフィールドを先に配置し、クエリの頻度が高いフィールドを先に配置してください。
Q EXPLAIN の「rows」の値は正確ですか?
A これらは推定値であり、正確な値ではありません。ただし、クエリの効率を評価する目安としては利用できます。
Q インデックスが効果を発揮しなくなった場合はどうすればよいですか?
A インデックスが効果を発揮しなくなる状況を避けるようSQLを書き直すか、関数インデックスを作成してください(MySQL 8.0以降)。
Q EXPLAIN の「rows」の値は正確ですか?
A これらは正確な値ではなく推定値ですが、相対的な変化を比較することで、最適化の効果を評価することができます。ANALYZE TABLE を使用して統計情報を更新してください。
Q プレフィックスインデックスはどのような場合に使用すべきですか?
A VARCHARフィールドが非常に長く、かつプレフィックスが十分に識別力がある場合です。例えば、INDEX(email(10))のように、最初の10文字の識別力が95%を超える場合です。

📖 まとめ


📝 練習問題

  1. 基本問題(難易度:⭐)EXPLAIN を使用してクエリを分析し、インデックスが使用されているかどうかを判断してください。

  2. 応用問題(難易度 ⭐⭐):左端プレフィックス原則を検証するための複合インデックスを作成してください。

  3. 課題問題(難易度:⭐⭐⭐):インデックスが効果を発揮しない3つのシナリオを挙げ、その解決策を提案してください。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%